Merge branch 'develop' into features/JAL-2379pcaMemory features/JAL-2379pcaMemory
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Thu, 9 Feb 2017 09:05:30 +0000 (09:05 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Thu, 9 Feb 2017 09:05:30 +0000 (09:05 +0000)
124 files changed:
examples/appletParameters.html
examples/groovy/colourSchemes.groovy [new file with mode: 0644]
help/html/colourSchemes/clustal.html
help/html/colourSchemes/user.html
help/html/io/tcoffeescores.html
resources/lang/Messages.properties
resources/lang/Messages_es.properties
src/MCview/AppletPDBViewer.java
src/MCview/PDBChain.java
src/MCview/PDBViewer.java [deleted file]
src/jalview/analysis/AlignmentUtils.java
src/jalview/analysis/Conservation.java
src/jalview/api/AlignViewportI.java
src/jalview/appletgui/APopupMenu.java
src/jalview/appletgui/AlignFrame.java
src/jalview/appletgui/AlignViewport.java
src/jalview/appletgui/AnnotationColourChooser.java
src/jalview/appletgui/AppletJmol.java
src/jalview/appletgui/FeatureRenderer.java
src/jalview/appletgui/SeqPanel.java
src/jalview/appletgui/SequenceRenderer.java
src/jalview/appletgui/SliderPanel.java
src/jalview/appletgui/TreeCanvas.java
src/jalview/appletgui/UserDefinedColours.java
src/jalview/bin/Cache.java
src/jalview/bin/Jalview.java
src/jalview/bin/JalviewLite.java
src/jalview/datamodel/Alignment.java
src/jalview/datamodel/AlignmentI.java
src/jalview/datamodel/AnnotatedCollectionI.java
src/jalview/datamodel/SequenceCollectionI.java
src/jalview/datamodel/SequenceGroup.java
src/jalview/ext/jmol/JalviewJmolBinding.java
src/jalview/ext/rbvi/chimera/ChimeraCommands.java
src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/AnnotationColourChooser.java
src/jalview/gui/AnnotationRowFilter.java
src/jalview/gui/AppJmol.java
src/jalview/gui/ChimeraViewFrame.java
src/jalview/gui/ColourMenuHelper.java [new file with mode: 0644]
src/jalview/gui/FeatureRenderer.java
src/jalview/gui/Jalview2XML.java
src/jalview/gui/Jalview2XML_V1.java
src/jalview/gui/JalviewChimeraBindingModel.java
src/jalview/gui/PCAPanel.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/Preferences.java
src/jalview/gui/SeqPanel.java
src/jalview/gui/SequenceRenderer.java
src/jalview/gui/SliderPanel.java
src/jalview/gui/StructureViewerBase.java
src/jalview/gui/TreeCanvas.java
src/jalview/gui/UserDefinedColours.java
src/jalview/io/AnnotationFile.java
src/jalview/io/FeaturesFile.java
src/jalview/io/JSONFile.java
src/jalview/io/TCoffeeScoreFile.java
src/jalview/jbgui/GAlignFrame.java
src/jalview/jbgui/GStructureViewer.java
src/jalview/jbgui/GUserDefinedColours.java
src/jalview/renderer/AnnotationRenderer.java
src/jalview/renderer/ResidueShader.java [new file with mode: 0644]
src/jalview/renderer/ResidueShaderI.java [new file with mode: 0644]
src/jalview/schemes/AnnotationColourGradient.java
src/jalview/schemes/Blosum62ColourScheme.java
src/jalview/schemes/BuriedColourScheme.java
src/jalview/schemes/ClustalxColourScheme.java
src/jalview/schemes/ColourSchemeI.java
src/jalview/schemes/ColourSchemeProperty.java
src/jalview/schemes/ColourSchemes.java [new file with mode: 0644]
src/jalview/schemes/CovariationColourScheme.java
src/jalview/schemes/FeatureColour.java
src/jalview/schemes/FollowerColourScheme.java
src/jalview/schemes/HelixColourScheme.java
src/jalview/schemes/HydrophobicColourScheme.java
src/jalview/schemes/JalviewColourScheme.java [new file with mode: 0644]
src/jalview/schemes/NucleotideColourScheme.java
src/jalview/schemes/PIDColourScheme.java
src/jalview/schemes/PurinePyrimidineColourScheme.java
src/jalview/schemes/RNAHelicesColour.java
src/jalview/schemes/RNAHelicesColourChooser.java
src/jalview/schemes/RNAInteractionColourScheme.java
src/jalview/schemes/ResidueColourScheme.java
src/jalview/schemes/ResidueProperties.java
src/jalview/schemes/ScoreColourScheme.java
src/jalview/schemes/StrandColourScheme.java
src/jalview/schemes/TCoffeeColourScheme.java
src/jalview/schemes/TaylorColourScheme.java
src/jalview/schemes/TurnColourScheme.java
src/jalview/schemes/UserColourScheme.java
src/jalview/schemes/ZappoColourScheme.java
src/jalview/structures/models/AAStructureBindingModel.java
src/jalview/util/ColorUtils.java
src/jalview/util/MappingUtils.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java
src/jalview/workers/ConsensusThread.java
src/jalview/ws/jws2/AADisorderClient.java
test/jalview/datamodel/AlignmentTest.java
test/jalview/datamodel/SequenceGroupTest.java [new file with mode: 0644]
test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java
test/jalview/gui/AlignFrameTest.java
test/jalview/gui/AlignViewportTest.java
test/jalview/gui/PopupMenuTest.java
test/jalview/io/AnnotationFileIOTest.java
test/jalview/io/FileFormatsTest.java
test/jalview/io/JSONFileTest.java
test/jalview/io/Jalview2xmlTests.java
test/jalview/io/JalviewFileViewTest.java
test/jalview/renderer/ResidueShaderTest.java [new file with mode: 0644]
test/jalview/renderer/ScaleRendererTest.java [new file with mode: 0644]
test/jalview/schemes/Blosum62ColourSchemeTest.java [new file with mode: 0644]
test/jalview/schemes/ClustalxColourSchemeTest.java [new file with mode: 0644]
test/jalview/schemes/ColourSchemePropertyTest.java [new file with mode: 0644]
test/jalview/schemes/ColourSchemesTest.java [new file with mode: 0644]
test/jalview/schemes/FeatureColourTest.java
test/jalview/schemes/JalviewColourSchemeTest.java [new file with mode: 0644]
test/jalview/schemes/PIDColourSchemeTest.java [new file with mode: 0644]
test/jalview/schemes/ResidueColourSchemeTest.java
test/jalview/schemes/UserColourSchemeTest.java
test/jalview/structures/models/AAStructureBindingModelTest.java
test/jalview/util/ColorUtilsTest.java

index 277fd69..7959c3a 100644 (file)
@@ -115,7 +115,7 @@ the applet can be interacted with <em>via</em> its
             <td>defaultColour</td>
             <td> <em>One of: </em><br>
               Clustal, Blosum62, % Identity, Hydrophobic, Zappo, Taylor, Helix 
-              Propensity, Strand Propensity, Turn Propensity, Buried Index, Nucleotide, T-Coffee Scores, RNA Helices</td>
+              Propensity, Strand Propensity, Turn Propensity, Buried Index, Nucleotide, Purine/Pyrimidine, T-Coffee Scores, RNA Helices</td>
             <td>Default is no colour.</td>
           </tr>
           <tr> 
diff --git a/examples/groovy/colourSchemes.groovy b/examples/groovy/colourSchemes.groovy
new file mode 100644 (file)
index 0000000..d5ca973
--- /dev/null
@@ -0,0 +1,155 @@
+import java.awt.Color;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ColourSchemes;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceI;
+import jalview.datamodel.SequenceCollectionI;
+
+/*
+ * Example script that registers two new alignment colour schemes
+ */
+
+/*
+ * Closure that defines a colour scheme where consensus residues are pink,
+ * other residues are red in odd columns and blue in even columns, and
+ * gaps are yellow  
+ */
+def candy
+candy = { ->
+  [
+    /*
+     * name shown in the colour menu
+     */
+    getSchemeName: { -> 'candy' },
+    
+    /*
+     * to make a new instance for each alignment view
+     */
+    getInstance: { AnnotatedCollectionI coll, Map<SequenceI, SequenceCollectionI> map -> candy() },
+    
+    /*
+     * method only needed if colour scheme has to recalculate
+     * values when an alignment is modified
+     */
+    alignmentChanged: { AnnotatedCollectionI coll, Map<SequenceI, SequenceCollectionI> map -> },
+    
+    /*
+     * determine colour for a residue at an aligned position of a
+     * sequence, given consensus residue(s) for the column and the
+     * consensus percentage identity score for the column
+     */
+    findColour: { char res, int col, SequenceI seq, String consensus, float pid -> 
+        if (res == ' ' || res == '-' || res == '.') 
+        {
+            Color.yellow
+        } else if (consensus.contains(String.valueOf(res)))
+        {
+            Color.pink
+        } else if (col % 2 == 0) 
+        {
+            Color.blue
+        } else 
+        {
+            Color.red
+        }
+    },
+    
+    /*
+     * true means applicable to nucleotide or peptide data
+     */
+    isApplicableTo: {AnnotatedCollectionI coll -> true},
+    
+    /*
+     * simple colour schemes are those that depend on the residue
+     * only (these are also available to colour structure viewers)
+     */
+    isSimple: { false }
+ ] as ColourSchemeI
+}
+
+/*
+ * A closure that defines a colour scheme graduated 
+ * (approximately) by amino acid weight
+ * here from lightest (G) Blue, to heaviest (W) Red
+ */
+def makeColour = { weight -> 
+    minWeight = 75 // Glycine
+    maxWeight = 204 // Tryptophan
+    int i = 255 * (weight - minWeight) / (maxWeight - minWeight);
+    new Color(i, 0, 255-i);
+}
+def byWeight
+byWeight = { ->
+  [
+    getSchemeName: { 'By Weight' },
+    // this colour scheme is peptide-specific:
+    isApplicableTo: { coll -> !coll.isNucleotide() },
+    alignmentChanged: { coll, map -> },
+    getInstance: { coll, map -> byWeight() },
+    isSimple: { true },
+    findColour: {res, col, seq, consensus, pid -> 
+        switch (res) {
+          case ' ':
+          case '-':
+          case '.':
+            Color.white
+             break
+          case 'A':
+            makeColour(89)
+            break
+          case 'R':
+            makeColour(174)
+            break
+          case 'N':
+          case 'D':
+          case 'B':
+          case 'I':
+          case 'L':
+            makeColour(132)
+            break
+          case 'C':
+            makeColour(121)
+            break
+          case 'Q':
+          case 'E':
+          case 'Z':
+          case 'K':
+          case 'M':
+            makeColour(146)
+            break
+          case 'G':
+            makeColour(75)
+            break
+          case 'H':
+            makeColour(155)
+            break
+          case 'F':
+            makeColour(165)
+            break
+          case 'P':
+            makeColour(115)
+            break
+          case 'S':
+            makeColour(105)
+            break
+          case 'T':
+            makeColour(119)
+            break
+          case 'W':
+            makeColour(204)
+            break
+          case 'Y':
+            makeColour(181)
+            break
+          case 'V':
+            makeColour(117)
+            break
+          default:
+            makeColour(150)
+        }
+      }
+  ] as ColourSchemeI
+}
+
+ColourSchemes.instance.registerColourScheme(candy())
+ColourSchemes.instance.registerColourScheme(byWeight())
index 7b68c84..b3d44db 100755 (executable)
@@ -40,9 +40,10 @@ td {
     is assigned a colour if the amino acid profile of the alignment at
     that position meets some minimum criteria specific for the residue
     type.</p>
-  <p>The table below gives these criteria as clauses: {+X%,xx,y},
-    where X is the minimum percentage presence for any of the xx (or y)
-    residue types.</p>
+  <p>The table below gives these criteria as clauses: {&gt;X%,xx,y},
+    where X is the threshold percentage presence for any of the xx (or y)
+    residue types.
+    <br>For example, K or R is coloured red if the column includes more than 60% K or R (combined), or more than 80% of either K or R or Q (individually).</p>
   <div align="center">
     <p>&nbsp;</p>
     <table border="1">
@@ -52,70 +53,81 @@ td {
       <tr>
         <td><table border="1">
             <tr>
+              <th>Category</th>
+              <th>Colour</th>
               <th>Residue at position</th>
-              <th>Applied Colour</th>
-              <th>{ Threshhold, Residue group }</th>
+              <th>{ Threshold, Residue group }</th>
             </tr>
             <tr>
+              <td rowspan="2">Hydrophobic</td>
+              <td rowspan="2" bgcolor="#80a0f0">BLUE</td>
               <td>A,I,L,M,F,W,V</td>
-              <td bgcolor="#80a0f0">BLUE</td>
-              <td>{+60%, WLVIMAFCHP}</td>
+              <td>{&gt;60%, WLVIMAFCHP}</td>
             </tr>
             <tr>
-              <td>R,K</td>
+              <td>C</td>
+              <td>{&gt;60%, WLVIMAFCHP}</td>
+            </tr>
+            <tr>
+              <td>Positive charge</td>
               <td bgcolor="#f01505">RED</td>
-              <td>{+60%,KR},{+80%, K,R,Q}</td>
+              <td>K,R</td>
+              <td>{&gt;60%,KR},{&gt;80%, K,R,Q}</td>
             </tr>
             <tr>
-              <td>N</td>
-              <td bgcolor="#15c015">GREEN</td>
-              <td>{+50%, N}, {+85%, N,Y}</td>
+              <td rowspan="2">Negative charge</td>
+              <td rowspan="2" bgcolor="#c048c0">MAGENTA</td>
+              <td>E</td>
+              <td>{&gt;60%,KR},{&gt;50%,QE},{&gt;85%,E,Q,D}</td>
             </tr>
             <tr>
-              <td>C</td>
-              <td bgcolor="#80a0f0">BLUE</td>
-              <td>{+60%, WLVIMAFCHP}</td>
+              <td>D</td>
+              <td>{&gt;60%,KR}, {&gt;85%, K,R,Q}, {&gt;50%,ED}</td>
             </tr>
             <tr>
-              <td>C</td>
-              <td bgcolor="#f08080">PINK</td>
-              <td>{100%, C}</td>
+              <td rowspan="3">Polar</td>
+              <td rowspan="3" bgcolor="#15c015">GREEN</td>
+              <td>N</td>
+              <td>{&gt;50%, N}, {&gt;85%, N,Y}</td>
             </tr>
             <tr>
               <td>Q</td>
-              <td bgcolor="#15c015">GREEN</td>
-              <td>{+60%,KR},{+50%,QE},{+85%,Q,E,K,R}</td>
+              <td>{&gt;60%,KR},{&gt;50%,QE},{&gt;85%,Q,E,K,R}</td>
             </tr>
             <tr>
-              <td>E</td>
-              <td bgcolor="#c048c0">MAGENTA</td>
-              <td>{+60%,KR},{+50%,QE},{+85%,E,Q,D}</td>
+              <td>S,T</td>
+              <td>{&gt;60%, WLVIMAFCHP}, {&gt;50%, TS}, {&gt;85%,S,T}</td>
             </tr>
             <tr>
-              <td>D</td>
-              <td bgcolor="#c048c0">MAGENTA</td>
-              <td>{+60%,KR}, {+85%, K,R,Q}, {+50%,ED}</td>
+              <td>Cysteines</td>
+              <td bgcolor="#f08080">PINK</td>
+              <td>C</td>
+              <td>{>85%, C}</td>
             </tr>
             <tr>
-              <td>G</td>
+              <td>Glycines</td>
               <td bgcolor="#f09048">ORANGE</td>
-              <td>{+0%, G}</td>
+              <td>G</td>
+              <td>{&gt;0%, G}</td>
             </tr>
             <tr>
-              <td>H,Y</td>
-              <td bgcolor="#15a4a4">CYAN</td>
-              <td>{+60%, WLVIMAFCHP}, {+85%,
-                W,Y,A,C,P,Q,F,H,I,L,M,V}</td>
+              <td>Prolines</td>
+              <td bgcolor="#c0c000">YELLOW</td>
+              <td>P</td>
+              <td>{&gt;0%, P}</td>
             </tr>
             <tr>
-              <td>P</td>
-              <td bgcolor="#c0c000">YELLOW</td>
-              <td>{+0%, P}</td>
+              <td>Aromatic</td>
+              <td bgcolor="#15a4a4">CYAN</td>
+              <td>H,Y</td>
+              <td>{&gt;60%, WLVIMAFCHP}, {&gt;85%,
+                W,Y,A,C,P,Q,F,H,I,L,M,V}</td>
             </tr>
             <tr>
-              <td>S,T</td>
-              <td bgcolor="#15c015">GREEN</td>
-              <td>{+60%, WLVIMAFCHP}, {+50%, TS}, {+85%,S,T}</td>
+              <td>Unconserved</td>
+              <td>WHITE</td>
+              <td>any / gap</td>
+              <td>If none of the above criteria are met</td>
             </tr>
           </table></td>
       </tr>
index 7239e4d..fb6c356 100755 (executable)
@@ -41,6 +41,9 @@
     The <strong>Case Sensitive</strong> option allows you to choose
     distinct colours for upper and lower case residue codes.
   <p>
+    The <strong>Lower Case Colour</strong> option allows you to apply a selected colour
+    to all lower case residues.
+  <p>
     Click <strong>Apply</strong> or <strong>OK</strong> to set your new
     colours on the active alignment window.<br /> Click <strong>Cancel</strong>
     to undo your changes if you pressed the <strong>Apply</strong>
index 08d1889..e67e3af 100644 (file)
@@ -79,6 +79,20 @@ cons   999999999999999999999999999851000110321100001134
 1QCF   ----------6878742356789999999999889
 cons   00100000006877641356789999999999889
 </pre>
-
+<table border="1">
+<tr><th>Score</th><th>0</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th><th>9</th></tr>
+<tr>
+<td>RGB colour</td>
+<td bgcolor="#6666FF">102, 102, 255</td>
+<td bgcolor="#00FF00">0, 255, 0</td>
+<td bgcolor="#66FF00">102, 255, 0</td>
+<td bgcolor="#CCFF00">204, 255, 0</td>
+<td bgcolor="#FFFF00">255, 255, 0</td>
+<td bgcolor="#FFCC00">255, 204, 0</td>
+<td bgcolor="#FF9900">255, 153, 0</td>
+<td bgcolor="#FF6600">255, 102, 0</td>
+<td bgcolor="#FF3300">255, 51, 0</td>
+<td bgcolor="#FF2000">255, 34, 0</td></tr>
+</table>
 </body>
 </html>
index 1352f0b..c451f07 100644 (file)
@@ -61,7 +61,6 @@ action.set_as_reference = Set as Reference
 action.remove = Remove
 action.remove_redundancy = Remove Redundancy...
 action.pairwise_alignment = Pairwise Alignment
-action.by_rna_helixes = By RNA Helices
 action.user_defined = User Defined...
 action.by_conservation = By Conservation
 action.wrap = Wrap
@@ -179,27 +178,30 @@ label.score_model_conservation = Physicochemical property conservation
 label.score_model_enhconservation = Physicochemical property conservation
 label.status_bar = Status bar
 label.out_to_textbox = Output to Textbox
-label.clustalx = Clustalx
+# delete Clustal - use FileFormat name instead
 label.clustal = Clustal
-label.zappo = Zappo
-label.taylor = Taylor
+# label.colourScheme_<schemeName> as in JalviewColourScheme
+label.colourScheme_clustal = Clustalx
+label.colourScheme_blosum62 = BLOSUM62 Score
+label.colourScheme_%_identity = Percentage Identity
+label.colourScheme_zappo = Zappo
+label.colourScheme_taylor = Taylor
+label.colourScheme_hydrophobic = Hydrophobicity
+label.colourScheme_helix_propensity = Helix Propensity
+label.colourScheme_strand_propensity = Strand Propensity
+label.colourScheme_turn_propensity = Turn Propensity
+label.colourScheme_buried_index = Buried Index
+label.colourScheme_purine/pyrimidine = Purine/Pyrimidine
+label.colourScheme_nucleotide = Nucleotide
+label.colourScheme_t-coffee_scores = T-Coffee Scores
+label.colourScheme_rna_helices = By RNA Helices
 label.blc = BLC
 label.fasta = Fasta
 label.msf = MSF
 label.pfam = PFAM
 label.pileup = Pileup
 label.pir = PIR
-label.hydrophobicity = Hydrophobicity
-label.helix_propensity = Helix Propensity
-label.strand_propensity = Strand Propensity
-label.turn_propensity = Turn Propensity
-label.buried_index = Buried Index
-label.purine_pyrimidine = Purine/Pyrimidine
-label.percentage_identity = Percentage Identity
-label.blosum62 = BLOSUM62
-label.blosum62_score = BLOSUM62 Score
-label.tcoffee_scores = T-Coffee Scores
-label.average_distance_bloslum62 = Average Distance Using BLOSUM62
+label.average_distance_blosum62 = Average Distance Using BLOSUM62
 label.neighbour_blosum62 = Neighbour Joining Using BLOSUM62
 label.show_annotations = Show annotations
 label.hide_annotations = Hide annotations
@@ -211,7 +213,7 @@ label.hide_all = Hide all
 label.add_reference_annotations = Add reference annotations
 label.find_tip = Search alignment, selection or sequence ids for a subsequence (ignoring gaps).<br>Accepts regular expressions - search Help for 'regex' for details.
 label.colour_text = Colour Text
-label.show_non_conversed = Show nonconserved
+label.show_non_conserved = Show nonconserved
 label.overview_window = Overview Window
 label.none = None
 label.above_identity_threshold = Above Identity Threshold
@@ -670,8 +672,6 @@ action.set_text_colour = Text Colour...
 label.structure = Structure
 label.show_pdbstruct_dialog = 3D Structure Data...
 label.view_rna_structure = VARNA 2D Structure
-label.clustalx_colours = Clustalx colours
-label.above_identity_percentage = Above % Identity
 label.create_sequence_details_report_annotation_for = Annotation for {0}
 label.sequence_details_for = Sequence Details for {0}
 label.sequence_name = Sequence Name
@@ -770,7 +770,7 @@ label.original_data_for_params = Original Data for {0}
 label.points_for_params = Points for {0}
 label.transformed_points_for_params = Transformed points for {0}
 label.graduated_color_for_params = Graduated Feature Colour for {0}
-label.select_backgroud_colour = Select Background Colour
+label.select_background_colour = Select Background Colour
 label.invalid_font = Invalid Font
 label.separate_multiple_accession_ids = Enter one or more accession IDs separated by a semi-colon ";"
 label.separate_multiple_query_values = Enter one or more {0}s separated by a semi-colon ";"
@@ -960,7 +960,6 @@ error.implementation_error_maplist_is_null = Implementation error. MapList is nu
 error.implementation_error_cannot_have_null_alignment = Implementation error: Cannot have null alignment property key
 error.implementation_error_null_fileparse = Implementation error. Null FileParse in copy constructor
 error.implementation_error_cannot_map_alignment_sequences = IMPLEMENTATION ERROR: Cannot map an alignment of sequences from different datasets into a single alignment in the vamsas document.
-error.implementation_error_cannot_duplicate_colour_scheme = Serious implementation error: cannot duplicate colourscheme {0}
 error.implementation_error_structure_selection_manager_null = Implementation error. Structure selection manager's context is 'null'
 exception.ssm_context_is_null = SSM context is null
 error.idstring_seqstrings_only_one_per_sequence = idstrings and seqstrings contain one string each per sequence
@@ -1025,7 +1024,6 @@ exception.replace_null_regex_pointer = Replacer has null Regex pointer
 exception.bad_pattern_to_regex_perl_code = bad pattern to Regex.perlCode: {0}
 exception.no_stub_implementation_for_interface = There is no stub implementation for the interface: {0}
 exception.cannot_set_endpoint_address_unknown_port = Cannot set Endpoint Address for Unknown Port {0}
-exception.querying_matching_opening_parenthesis_for_non_closing_parenthesis = Querying matching opening parenthesis for non-closing parenthesis character {0}
 exception.mismatched_unseen_closing_char = Mismatched (unseen) closing character {0}
 exception.mismatched_closing_char = Mismatched closing character {0}
 exception.mismatched_opening_char = Mismatched opening character {0} at {1}
@@ -1036,7 +1034,6 @@ exception.couldnt_parse_responde_from_annotated3d_server = Couldn't parse respon
 exception.application_test_npe = Application test: throwing an NullPointerException It should arrive at the console
 exception.overwriting_vamsas_id_binding = Overwriting vamsas id binding
 exception.overwriting_jalview_id_binding = Overwriting jalview id binding
-error.implementation_error_unknown_file_format_string = Implementation error: Unknown file format string
 exception.failed_to_resolve_gzip_stream = Failed to resolve GZIP stream
 exception.problem_opening_file_also_tried = Problem opening {0} (also tried {1}) : {2}
 exception.problem_opening_file = Problem opening {0} : {1}
@@ -1232,7 +1229,6 @@ action.export_hidden_columns = Export Hidden Columns
 action.export_hidden_sequences = Export Hidden Sequences
 action.export_features = Export Features
 label.export_settings = Export Settings
-label.save_as_biojs_html = Save as BioJs HTML
 label.pdb_web-service_error = PDB Web-service Error
 label.structure_chooser_manual_association = Structure Chooser - Manual association
 label.structure_chooser_filter_time = Structure Chooser - Filter time ({0})
index 8cdcd52..0a330b9 100644 (file)
@@ -59,7 +59,6 @@ action.by_group = Por grupo
 action.remove = Eliminar
 action.remove_redundancy = Eliminar redundancia...
 action.pairwise_alignment = Alineamiento de pares...
-action.by_rna_helixes = Por hélices de RNA
 action.user_defined = Definido por el usuario...
 action.by_conservation = Por conservación
 action.wrap = Envolver
@@ -176,31 +175,33 @@ label.score_model_conservation = Conservaci
 label.score_model_enhconservation = Conservación de las propiedades físico-químicas
 label.status_bar = Barra de estado
 label.out_to_textbox = Generar cuadro de texto
-label.clustalx = Clustalx
 label.clustal = Clustal
-label.zappo = Zappo
-label.taylor = Taylor
+# label.colourScheme_<schemeName> as in JalviewColourScheme
+label.colourScheme_clustal = Clustalx
+label.colourScheme_blosum62 = Puntuación del BLOSUM62
+label.colourScheme_%_identity = Porcentaje de identidad
+label.colourScheme_zappo = Zappo
+label.colourScheme_taylor = Taylor
+label.colourScheme_hydrophobic = Hidrofobicidad
+label.colourScheme_helix_propensity = Tendencia de la hélice
+label.colourScheme_strand_propensity = Tendencia de la hebra
+label.colourScheme_turn_propensity = Tendencia de giro
+label.colourScheme_buried_index = Índice de encubrimiento
+label.colourScheme_purine/pyrimidine = Purina/Pirimidina
+label.colourScheme_nucleotide = Nucleótido
+label.colourScheme_t-coffee_scores = Puntuación del T-Coffee
+label.colourScheme_rna_helices = Por hélices de RNA
 label.blc = BLC
 label.fasta = Fasta
 label.msf = MSF
 label.pfam = PFAM
 label.pileup = Pileup
 label.pir = PIR
-label.hydrophobicity = Hidrofobicidad
-label.helix_propensity = Tendencia de la hélice
-label.strand_propensity = Tendencia de la hebra
-label.turn_propensity = Tendencia de giro
-label.buried_index = Índice de encubrimiento
-label.purine_pyrimidine = Purina/Pirimidina
-label.percentage_identity = Porcentaje de identidad
-label.blosum62 = BLOSUM62
-label.blosum62_score = Puntuación del BLOSUM62 
-label.tcoffee_scores = Puntuación del T-Coffee
-label.average_distance_bloslum62 = Distancia Media Usando BLOSUM62
+label.average_distance_blosum62 = Distancia Media Usando BLOSUM62
 label.neighbour_blosum62 = Neighbour Joining usando BLOSUM62
 label.show_annotations = Mostrar anotaciones
 label.colour_text = Color del texto
-label.show_non_conversed = Mostrar no conservadas
+label.show_non_conserved = Mostrar no conservadas
 label.overview_window = Ventana resumen
 label.none = Ninguno
 label.above_identity_threshold = Por encima del umbral de identidad
@@ -293,7 +294,7 @@ label.size = Talla:
 label.style = Estilo:
 label.calculating = Calculando....
 label.modify_conservation_visibility = Modificar la visibilidad de conservación
-label.colour_residues_above_occurence = Residuos de color por encima del % de aparición 
+label.colour_residues_above_occurrence = Residuos de color por encima del % de aparición 
 label.set_this_label_text = fijar como etiqueta 
 label.sequences_from = Secuencias de {0}
 label.successfully_loaded_file  = Fichero cargado exitosamente {0}
@@ -622,8 +623,6 @@ label.from_file = desde fichero
 label.enter_pdb_id = Introducir PDB Id
 label.text_colour = Color del texto
 label.structure = Estructura
-label.clustalx_colours = Colores de Clustalx
-label.above_identity_percentage = Sobre % identidad
 label.create_sequence_details_report_annotation_for = Anotación para {0}
 label.sequence_details_for = Detalles de la secuencia para {0}
 label.sequence_name = Nombre de la secuencia
@@ -707,7 +706,7 @@ label.original_data_for_params = Datos originales de {0}
 label.points_for_params = Puntos de {0}
 label.transformed_points_for_params = Puntos transformados de {0}
 label.graduated_color_for_params = Color graduado para la característica de {0}
-label.select_backgroud_colour = Seleccionar color de fondo
+label.select_background_colour = Seleccionar color de fondo
 label.invalid_font = Fuente no válida
 label.separate_multiple_accession_ids = Separar los accession id con un punto y coma ";"
 label.replace_commas_semicolons = Cambiar comas por puntos y comas
@@ -893,7 +892,6 @@ error.implementation_error_maplist_is_null = Error de implementaci
 error.implementation_error_cannot_have_null_alignment = Error de implementación: no es posible tener una clave nula en el alineamiento
 error.implementation_error_null_fileparse = Error de implementación. FileParse nulo en el construictor de copia
 error.implementation_error_cannot_map_alignment_sequences = Error de implementación: no es posible maper un alineamiento de secuencias desde distintos conjuntos de datos en un único alineamiento en el documento VAMSAS.
-error.implementation_error_cannot_duplicate_colour_scheme = Error grave de implementación: no es posible duplicar el esquema cromático {0}
 error.implementation_error_structure_selection_manager_null = Error de implementación. El contexto structure selection manager's es nulo
 exception.ssm_context_is_null = El contexto SSM es nulo
 error.idstring_seqstrings_only_one_per_sequence = idstrings y seqstrings contienen una cadena por cada secuencia
@@ -958,7 +956,6 @@ exception.replace_null_regex_pointer = Reemplazador tiene un puntero Regex nulo
 exception.bad_pattern_to_regex_perl_code = patrón erróneo en Regex.perlCode: {0}
 exception.no_stub_implementation_for_interface = No existe una implementación del stub para la interfaz: {0}
 exception.cannot_set_endpoint_address_unknown_port = No es posible estabelcer la dirección de punto final para el puerto desconocido {0}
-exception.querying_matching_opening_parenthesis_for_non_closing_parenthesis = Consultando la coincidencia de apertura de paréntesis para paréntesis sin cerrar (?)
 exception.mismatched_unseen_closing_char = Discordancia (no vista) en el carácter de cierre {0}
 exception.mismatched_closing_char = Carácter de cierre discordante {0}
 exception.mismatched_opening_char = Carácter de apertura discordante {0} en {1}
@@ -969,7 +966,6 @@ exception.couldnt_parse_responde_from_annotated3d_server = No es posible parsear
 exception.application_test_npe = Prueba de aplicación: lanzando un NullPointerException que debe aparecer en la consola
 exception.overwriting_vamsas_id_binding = Sobreescribiendo la asociación al VAMSAS id
 exception.overwriting_jalview_id_binding = Sobreescribiendo la asociación al Jalview id
-error.implementation_error_unknown_file_format_string = Error de implementación: cadena de formato de fichero desconocido
 exception.failed_to_resolve_gzip_stream = Fallo al resolver el flujo GZIP 
 exception.problem_opening_file_also_tried = Problema abriendo {0} (también se intentó {1}) : {2}
 exception.problem_opening_file = Problema abriendo {0} : {1}
@@ -1233,7 +1229,6 @@ tooltip.aacon_calculations=Actualizar c
 info.select_filter_option=Escoger Opción de Filtro / Entrada Manual
 info.invalid_msa_input_mininfo=Necesita por lo menos dos secuencias con al menos 3 residuos cada una, sin regiones ocultas entre ellas.
 label.chimera_missing=Visualizador de estructura Chimera no encontrado.<br/>Por favor, introduzca la ruta de Chimera,<br/>o descargar e instalar la UCSF Chimera.
-label.save_as_biojs_html=Guardar como HTML BioJs
 exception.fts_server_unreachable=Jalview no puede conectar con el servidor {0}. \nPor favor asegúrese de que está conectado a Internet y vuelva a intentarlo.
 exception.outofmemory_loading_mmcif_file=Sin memoria al cargar el fichero mmCIF
 label.hide_columns_not_containing=Ocultar las columnas que no contengan
index 76ee4b0..133565c 100644 (file)
@@ -185,7 +185,8 @@ public class AppletPDBViewer extends EmbmenuFrame implements
     zbuffer.addItemListener(this);
     charge.setLabel(MessageManager.getString("label.charge_cysteine"));
     charge.addActionListener(this);
-    hydro.setLabel(MessageManager.getString("label.hydrophobicity"));
+    hydro.setLabel(MessageManager
+            .getString("label.colourScheme_hydrophobic"));
     hydro.addActionListener(this);
     chain.setLabel(MessageManager.getString("action.by_chain"));
     chain.addActionListener(this);
@@ -195,17 +196,21 @@ public class AppletPDBViewer extends EmbmenuFrame implements
             .setLabel(MessageManager.getString("label.all_chains_visible"));
     allchains.addItemListener(this);
     viewMenu.setLabel(MessageManager.getString("action.view"));
-    zappo.setLabel(MessageManager.getString("label.zappo"));
+    zappo.setLabel(MessageManager.getString("label.colourScheme_zappo"));
     zappo.addActionListener(this);
-    taylor.setLabel(MessageManager.getString("label.taylor"));
+    taylor.setLabel(MessageManager.getString("label.colourScheme_taylor"));
     taylor.addActionListener(this);
-    helix.setLabel(MessageManager.getString("label.helix_propensity"));
+    helix.setLabel(MessageManager
+            .getString("label.colourScheme_helix_propensity"));
     helix.addActionListener(this);
-    strand.setLabel(MessageManager.getString("label.strand_propensity"));
+    strand.setLabel(MessageManager
+            .getString("label.colourScheme_strand_propensity"));
     strand.addActionListener(this);
-    turn.setLabel(MessageManager.getString("label.turn_propensity"));
+    turn.setLabel(MessageManager
+            .getString("label.colourScheme_turn_propensity"));
     turn.addActionListener(this);
-    buried.setLabel(MessageManager.getString("label.buried_index"));
+    buried.setLabel(MessageManager
+            .getString("label.colourScheme_buried_index"));
     buried.addActionListener(this);
     user.setLabel(MessageManager.getString("action.user_defined"));
     user.addActionListener(this);
index 783a4e2..c40cdda 100755 (executable)
@@ -516,10 +516,12 @@ public class PDBChain
       try
       {
         index = ResidueProperties.aa3Hash.get(b.at1.resName).intValue();
-        b.startCol = cs.findColour(ResidueProperties.aa[index].charAt(0));
+        b.startCol = cs.findColour(ResidueProperties.aa[index].charAt(0),
+                0, null, null, 0f);
 
         index = ResidueProperties.aa3Hash.get(b.at2.resName).intValue();
-        b.endCol = cs.findColour(ResidueProperties.aa[index].charAt(0));
+        b.endCol = cs.findColour(ResidueProperties.aa[index].charAt(0), 0,
+                null, null, 0f);
 
       } catch (Exception e)
       {
diff --git a/src/MCview/PDBViewer.java b/src/MCview/PDBViewer.java
deleted file mode 100755 (executable)
index f108fc2..0000000
+++ /dev/null
@@ -1,784 +0,0 @@
-/*
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
- * Copyright (C) $$Year-Rel$$ The Jalview Authors
- * 
- * This file is part of Jalview.
- * 
- * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License 
- * as published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *  
- * Jalview is distributed in the hope that it will be useful, but 
- * WITHOUT ANY WARRANTY; without even the implied warranty 
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
- * PURPOSE.  See the GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
- * The Jalview Authors are detailed in the 'AUTHORS' file.
- */
-package MCview;
-
-import jalview.datamodel.PDBEntry;
-import jalview.datamodel.SequenceI;
-import jalview.gui.AlignmentPanel;
-import jalview.gui.Desktop;
-import jalview.gui.JvOptionPane;
-import jalview.gui.OOMWarning;
-import jalview.gui.UserDefinedColours;
-import jalview.io.DataSourceType;
-import jalview.io.JalviewFileChooser;
-import jalview.io.JalviewFileView;
-import jalview.schemes.BuriedColourScheme;
-import jalview.schemes.HelixColourScheme;
-import jalview.schemes.HydrophobicColourScheme;
-import jalview.schemes.StrandColourScheme;
-import jalview.schemes.TaylorColourScheme;
-import jalview.schemes.TurnColourScheme;
-import jalview.schemes.UserColourScheme;
-import jalview.schemes.ZappoColourScheme;
-import jalview.util.MessageManager;
-import jalview.ws.ebi.EBIFetchClient;
-
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-import java.awt.event.KeyAdapter;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.PrintWriter;
-
-import javax.swing.ButtonGroup;
-import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JColorChooser;
-import javax.swing.JInternalFrame;
-import javax.swing.JMenu;
-import javax.swing.JMenuBar;
-import javax.swing.JMenuItem;
-import javax.swing.JRadioButtonMenuItem;
-
-public class PDBViewer extends JInternalFrame implements Runnable
-{
-
-  /**
-   * The associated sequence in an alignment
-   */
-  PDBCanvas pdbcanvas;
-
-  PDBEntry pdbentry;
-
-  SequenceI[] seq;
-
-  String[] chains;
-
-  AlignmentPanel ap;
-
-  DataSourceType protocol;
-
-  String tmpPDBFile;
-
-  public PDBViewer(PDBEntry pdbentry, SequenceI[] seq, String[] chains,
-          AlignmentPanel ap, DataSourceType protocol)
-  {
-    this.pdbentry = pdbentry;
-    this.seq = seq;
-    this.chains = chains;
-    this.ap = ap;
-    this.protocol = protocol;
-
-    try
-    {
-      jbInit();
-    } catch (Exception ex)
-    {
-      ex.printStackTrace();
-    }
-
-    StringBuffer title = new StringBuffer(seq[0].getName() + ":"
-            + pdbentry.getFile());
-
-    pdbcanvas = new PDBCanvas();
-
-    setContentPane(pdbcanvas);
-
-    if (pdbentry.getFile() != null)
-    {
-      try
-      {
-        tmpPDBFile = pdbentry.getFile();
-        PDBfile pdbfile = new PDBfile(false, false, false, tmpPDBFile,
-                DataSourceType.FILE);
-
-        pdbcanvas.init(pdbentry, seq, chains, ap, protocol);
-
-      } catch (java.io.IOException ex)
-      {
-        ex.printStackTrace();
-      }
-    }
-    else
-    {
-      Thread worker = new Thread(this);
-      worker.start();
-    }
-
-    String method = (String) pdbentry.getProperty("method");
-    if (method != null)
-    {
-      title.append(" Method: ");
-      title.append(method);
-    }
-    String ch = (String) pdbentry.getProperty("chains");
-    if (ch != null)
-    {
-      title.append(" Chain:");
-      title.append(ch);
-    }
-    Desktop.addInternalFrame(this, title.toString(), 400, 400);
-  }
-
-  @Override
-  public void run()
-  {
-    try
-    {
-      EBIFetchClient ebi = new EBIFetchClient();
-      String query = "pdb:" + pdbentry.getId();
-      pdbentry.setFile(ebi.fetchDataAsFile(query, "default", "xml")
-              .getAbsolutePath());
-
-      if (pdbentry.getFile() != null)
-      {
-        pdbcanvas.init(pdbentry, seq, chains, ap, protocol);
-      }
-    } catch (Exception ex)
-    {
-      pdbcanvas.errorMessage = "Error retrieving file: " + pdbentry.getId();
-      ex.printStackTrace();
-    }
-  }
-
-  private void jbInit() throws Exception
-  {
-    this.addKeyListener(new KeyAdapter()
-    {
-      @Override
-      public void keyPressed(KeyEvent evt)
-      {
-        pdbcanvas.keyPressed(evt);
-      }
-    });
-
-    this.setJMenuBar(jMenuBar1);
-    fileMenu.setText(MessageManager.getString("action.file"));
-    coloursMenu.setText(MessageManager.getString("label.colours"));
-    saveMenu.setActionCommand(MessageManager.getString("action.save_image"));
-    saveMenu.setText(MessageManager.getString("action.save_as"));
-    png.setText("PNG");
-    png.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        png_actionPerformed(e);
-      }
-    });
-    eps.setText("EPS");
-    eps.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        eps_actionPerformed(e);
-      }
-    });
-    mapping.setText(MessageManager.getString("label.view_mapping"));
-    mapping.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        mapping_actionPerformed(e);
-      }
-    });
-    wire.setText(MessageManager.getString("label.wireframe"));
-    wire.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        wire_actionPerformed(e);
-      }
-    });
-    depth.setSelected(true);
-    depth.setText(MessageManager.getString("label.depthcue"));
-    depth.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        depth_actionPerformed(e);
-      }
-    });
-    zbuffer.setSelected(true);
-    zbuffer.setText(MessageManager.getString("label.z_buffering"));
-    zbuffer.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        zbuffer_actionPerformed(e);
-      }
-    });
-    charge.setText(MessageManager.getString("label.charge_cysteine"));
-    charge.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        charge_actionPerformed(e);
-      }
-    });
-    chain.setText(MessageManager.getString("action.by_chain"));
-    chain.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        chain_actionPerformed(e);
-      }
-    });
-    seqButton.setSelected(true);
-    seqButton.setText(MessageManager.getString("action.by_sequence"));
-    seqButton.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        seqButton_actionPerformed(e);
-      }
-    });
-    allchains.setSelected(true);
-    allchains.setText(MessageManager.getString("label.show_all_chains"));
-    allchains.addItemListener(new ItemListener()
-    {
-      @Override
-      public void itemStateChanged(ItemEvent e)
-      {
-        allchains_itemStateChanged(e);
-      }
-    });
-    zappo.setText(MessageManager.getString("label.zappo"));
-    zappo.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        zappo_actionPerformed(e);
-      }
-    });
-    taylor.setText(MessageManager.getString("label.taylor"));
-    taylor.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        taylor_actionPerformed(e);
-      }
-    });
-    hydro.setText(MessageManager.getString("label.hydrophobicity"));
-    hydro.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        hydro_actionPerformed(e);
-      }
-    });
-    helix.setText(MessageManager.getString("label.helix_propensity"));
-    helix.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        helix_actionPerformed(e);
-      }
-    });
-    strand.setText(MessageManager.getString("label.strand_propensity"));
-    strand.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        strand_actionPerformed(e);
-      }
-    });
-    turn.setText(MessageManager.getString("label.turn_propensity"));
-    turn.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        turn_actionPerformed(e);
-      }
-    });
-    buried.setText(MessageManager.getString("label.buried_index"));
-    buried.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        buried_actionPerformed(e);
-      }
-    });
-    user.setText(MessageManager.getString("action.user_defined"));
-    user.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        user_actionPerformed(e);
-      }
-    });
-    viewMenu.setText(MessageManager.getString("action.view"));
-    background
-            .setText(MessageManager.getString("action.background_colour"));
-    background.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        background_actionPerformed(e);
-      }
-    });
-    savePDB.setText(MessageManager.getString("label.pdb_file"));
-    savePDB.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        savePDB_actionPerformed(e);
-      }
-    });
-    jMenuBar1.add(fileMenu);
-    jMenuBar1.add(coloursMenu);
-    jMenuBar1.add(viewMenu);
-    fileMenu.add(saveMenu);
-    fileMenu.add(mapping);
-    saveMenu.add(savePDB);
-    saveMenu.add(png);
-    saveMenu.add(eps);
-    coloursMenu.add(seqButton);
-    coloursMenu.add(chain);
-    coloursMenu.add(charge);
-    coloursMenu.add(zappo);
-    coloursMenu.add(taylor);
-    coloursMenu.add(hydro);
-    coloursMenu.add(helix);
-    coloursMenu.add(strand);
-    coloursMenu.add(turn);
-    coloursMenu.add(buried);
-    coloursMenu.add(user);
-    coloursMenu.add(background);
-    ButtonGroup bg = new ButtonGroup();
-    bg.add(seqButton);
-    bg.add(chain);
-    bg.add(charge);
-    bg.add(zappo);
-    bg.add(taylor);
-    bg.add(hydro);
-    bg.add(helix);
-    bg.add(strand);
-    bg.add(turn);
-    bg.add(buried);
-    bg.add(user);
-
-    if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
-    {
-      java.util.Enumeration userColours = jalview.gui.UserDefinedColours
-              .getUserColourSchemes().keys();
-
-      while (userColours.hasMoreElements())
-      {
-        final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(
-                userColours.nextElement().toString());
-        radioItem.setName("USER_DEFINED");
-        radioItem.addMouseListener(new MouseAdapter()
-        {
-          @Override
-          public void mousePressed(MouseEvent evt)
-          {
-            if (evt.isPopupTrigger()) // Mac
-            {
-              offerRemoval(radioItem);
-            }
-          }
-
-          @Override
-          public void mouseReleased(MouseEvent evt)
-          {
-            if (evt.isPopupTrigger()) // Windows
-            {
-              offerRemoval(radioItem);
-            }
-          }
-
-          /**
-           * @param radioItem
-           */
-          void offerRemoval(final JRadioButtonMenuItem radioItem)
-          {
-            radioItem.removeActionListener(radioItem.getActionListeners()[0]);
-
-            int option = JvOptionPane.showInternalConfirmDialog(
-                    jalview.gui.Desktop.desktop, MessageManager
-                            .getString("label.remove_from_default_list"),
-                    MessageManager
-                            .getString("label.remove_user_defined_colour"),
-                    JvOptionPane.YES_NO_OPTION);
-            if (option == JvOptionPane.YES_OPTION)
-            {
-              jalview.gui.UserDefinedColours
-                      .removeColourFromDefaults(radioItem.getText());
-              coloursMenu.remove(radioItem);
-            }
-            else
-            {
-              radioItem.addActionListener(new ActionListener()
-              {
-                @Override
-                public void actionPerformed(ActionEvent evt)
-                {
-                  user_actionPerformed(evt);
-                }
-              });
-            }
-          }
-        });
-        radioItem.addActionListener(new ActionListener()
-        {
-          @Override
-          public void actionPerformed(ActionEvent evt)
-          {
-            user_actionPerformed(evt);
-          }
-        });
-        coloursMenu.add(radioItem);
-        bg.add(radioItem);
-      }
-    }
-
-    viewMenu.add(wire);
-    viewMenu.add(depth);
-    viewMenu.add(zbuffer);
-    viewMenu.add(allchains);
-  }
-
-  JMenuBar jMenuBar1 = new JMenuBar();
-
-  JMenu fileMenu = new JMenu();
-
-  JMenu coloursMenu = new JMenu();
-
-  JMenu saveMenu = new JMenu();
-
-  JMenuItem png = new JMenuItem();
-
-  JMenuItem eps = new JMenuItem();
-
-  JMenuItem mapping = new JMenuItem();
-
-  JCheckBoxMenuItem wire = new JCheckBoxMenuItem();
-
-  JCheckBoxMenuItem depth = new JCheckBoxMenuItem();
-
-  JCheckBoxMenuItem zbuffer = new JCheckBoxMenuItem();
-
-  JCheckBoxMenuItem allchains = new JCheckBoxMenuItem();
-
-  JRadioButtonMenuItem charge = new JRadioButtonMenuItem();
-
-  JRadioButtonMenuItem chain = new JRadioButtonMenuItem();
-
-  JRadioButtonMenuItem seqButton = new JRadioButtonMenuItem();
-
-  JRadioButtonMenuItem hydro = new JRadioButtonMenuItem();
-
-  JRadioButtonMenuItem taylor = new JRadioButtonMenuItem();
-
-  JRadioButtonMenuItem zappo = new JRadioButtonMenuItem();
-
-  JRadioButtonMenuItem user = new JRadioButtonMenuItem();
-
-  JRadioButtonMenuItem buried = new JRadioButtonMenuItem();
-
-  JRadioButtonMenuItem turn = new JRadioButtonMenuItem();
-
-  JRadioButtonMenuItem strand = new JRadioButtonMenuItem();
-
-  JRadioButtonMenuItem helix = new JRadioButtonMenuItem();
-
-  JMenu viewMenu = new JMenu();
-
-  JMenuItem background = new JMenuItem();
-
-  JMenuItem savePDB = new JMenuItem();
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  public void eps_actionPerformed(ActionEvent e)
-  {
-    makePDBImage(jalview.util.ImageMaker.TYPE.EPS);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  public void png_actionPerformed(ActionEvent e)
-  {
-    makePDBImage(jalview.util.ImageMaker.TYPE.PNG);
-  }
-
-  void makePDBImage(jalview.util.ImageMaker.TYPE type)
-  {
-    int width = pdbcanvas.getWidth();
-    int height = pdbcanvas.getHeight();
-
-    jalview.util.ImageMaker im;
-
-    if (type == jalview.util.ImageMaker.TYPE.PNG)
-    {
-      im = new jalview.util.ImageMaker(this,
-              jalview.util.ImageMaker.TYPE.PNG, "Make PNG image from view",
-              width, height, null, null, null, 0, false);
-    }
-    else if (type == jalview.util.ImageMaker.TYPE.EPS)
-    {
-      im = new jalview.util.ImageMaker(this,
-              jalview.util.ImageMaker.TYPE.EPS, "Make EPS file from view",
-              width, height, null, this.getTitle(), null, 0, false);
-    }
-    else
-    {
-
-      im = new jalview.util.ImageMaker(this,
-              jalview.util.ImageMaker.TYPE.SVG, "Make SVG file from PCA",
-              width, height, null, this.getTitle(), null, 0, false);
-    }
-
-    if (im.getGraphics() != null)
-    {
-      pdbcanvas.drawAll(im.getGraphics(), width, height);
-      im.writeImage();
-    }
-  }
-
-  public void charge_actionPerformed(ActionEvent e)
-  {
-    pdbcanvas.bysequence = false;
-    pdbcanvas.pdb.setChargeColours();
-    pdbcanvas.redrawneeded = true;
-    pdbcanvas.repaint();
-  }
-
-  public void hydro_actionPerformed(ActionEvent e)
-  {
-    pdbcanvas.bysequence = false;
-    pdbcanvas.pdb.setColours(new HydrophobicColourScheme());
-    pdbcanvas.redrawneeded = true;
-    pdbcanvas.repaint();
-  }
-
-  public void chain_actionPerformed(ActionEvent e)
-  {
-    pdbcanvas.bysequence = false;
-    pdbcanvas.pdb.setChainColours();
-    pdbcanvas.redrawneeded = true;
-    pdbcanvas.repaint();
-  }
-
-  public void zbuffer_actionPerformed(ActionEvent e)
-  {
-    pdbcanvas.zbuffer = !pdbcanvas.zbuffer;
-    pdbcanvas.redrawneeded = true;
-    pdbcanvas.repaint();
-  }
-
-  public void molecule_actionPerformed(ActionEvent e)
-  {
-    pdbcanvas.bymolecule = !pdbcanvas.bymolecule;
-    pdbcanvas.redrawneeded = true;
-    pdbcanvas.repaint();
-  }
-
-  public void depth_actionPerformed(ActionEvent e)
-  {
-    pdbcanvas.depthcue = !pdbcanvas.depthcue;
-    pdbcanvas.redrawneeded = true;
-    pdbcanvas.repaint();
-  }
-
-  public void wire_actionPerformed(ActionEvent e)
-  {
-    pdbcanvas.wire = !pdbcanvas.wire;
-    pdbcanvas.redrawneeded = true;
-    pdbcanvas.repaint();
-  }
-
-  public void seqButton_actionPerformed(ActionEvent e)
-  {
-    pdbcanvas.bysequence = true;
-    pdbcanvas.updateSeqColours();
-  }
-
-  public void mapping_actionPerformed(ActionEvent e)
-  {
-    jalview.gui.CutAndPasteTransfer cap = new jalview.gui.CutAndPasteTransfer();
-    try
-    {
-      cap.setText(pdbcanvas.mappingDetails.toString());
-      Desktop.addInternalFrame(cap,
-              MessageManager.getString("label.pdb_sequence_mapping"), 550,
-              600);
-    } catch (OutOfMemoryError oom)
-    {
-      new OOMWarning("Opening sequence to structure mapping report", oom);
-      cap.dispose();
-    }
-  }
-
-  public void allchains_itemStateChanged(ItemEvent e)
-  {
-    pdbcanvas.setAllchainsVisible(allchains.getState());
-  }
-
-  public void zappo_actionPerformed(ActionEvent e)
-  {
-    pdbcanvas.bysequence = false;
-    pdbcanvas.pdb.setColours(new ZappoColourScheme());
-    pdbcanvas.redrawneeded = true;
-    pdbcanvas.repaint();
-  }
-
-  public void taylor_actionPerformed(ActionEvent e)
-  {
-    pdbcanvas.bysequence = false;
-    pdbcanvas.pdb.setColours(new TaylorColourScheme());
-    pdbcanvas.redrawneeded = true;
-    pdbcanvas.repaint();
-  }
-
-  public void helix_actionPerformed(ActionEvent e)
-  {
-    pdbcanvas.bysequence = false;
-    pdbcanvas.pdb.setColours(new HelixColourScheme());
-    pdbcanvas.redrawneeded = true;
-    pdbcanvas.repaint();
-  }
-
-  public void strand_actionPerformed(ActionEvent e)
-  {
-    pdbcanvas.bysequence = false;
-    pdbcanvas.pdb.setColours(new StrandColourScheme());
-    pdbcanvas.redrawneeded = true;
-    pdbcanvas.repaint();
-  }
-
-  public void turn_actionPerformed(ActionEvent e)
-  {
-    pdbcanvas.bysequence = false;
-    pdbcanvas.pdb.setColours(new TurnColourScheme());
-    pdbcanvas.redrawneeded = true;
-    pdbcanvas.repaint();
-  }
-
-  public void buried_actionPerformed(ActionEvent e)
-  {
-    pdbcanvas.bysequence = false;
-    pdbcanvas.pdb.setColours(new BuriedColourScheme());
-    pdbcanvas.redrawneeded = true;
-    pdbcanvas.repaint();
-  }
-
-  public void user_actionPerformed(ActionEvent e)
-  {
-    if (e.getActionCommand().equals(
-            MessageManager.getString("action.user_defined")))
-    {
-      // new UserDefinedColours(pdbcanvas, null);
-    }
-    else
-    {
-      UserColourScheme udc = (UserColourScheme) UserDefinedColours
-              .getUserColourSchemes().get(e.getActionCommand());
-
-      pdbcanvas.pdb.setColours(udc);
-      pdbcanvas.redrawneeded = true;
-      pdbcanvas.repaint();
-    }
-  }
-
-  public void background_actionPerformed(ActionEvent e)
-  {
-    java.awt.Color col = JColorChooser.showDialog(this,
-            MessageManager.getString("label.select_backgroud_colour"),
-            pdbcanvas.backgroundColour);
-
-    if (col != null)
-    {
-      pdbcanvas.backgroundColour = col;
-      pdbcanvas.redrawneeded = true;
-      pdbcanvas.repaint();
-    }
-  }
-
-  public void savePDB_actionPerformed(ActionEvent e)
-  {
-    JalviewFileChooser chooser = new JalviewFileChooser(
-            jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
-
-    chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager.getString("label.save_pdb_file"));
-    chooser.setToolTipText(MessageManager.getString("action.save"));
-
-    int value = chooser.showSaveDialog(this);
-
-    if (value == JalviewFileChooser.APPROVE_OPTION)
-    {
-      try
-      {
-        BufferedReader in = new BufferedReader(new FileReader(tmpPDBFile));
-        File outFile = chooser.getSelectedFile();
-
-        PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
-        String data;
-        while ((data = in.readLine()) != null)
-        {
-          if (!(data.indexOf("<PRE>") > -1 || data.indexOf("</PRE>") > -1))
-          {
-            out.println(data);
-          }
-        }
-        out.close();
-        in.close();
-      } catch (Exception ex)
-      {
-        ex.printStackTrace();
-      }
-    }
-  }
-}
index 34fe221..ea96b3b 100644 (file)
@@ -60,6 +60,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.NoSuchElementException;
 import java.util.Set;
+import java.util.SortedMap;
 import java.util.TreeMap;
 
 /**
@@ -2840,7 +2841,7 @@ public class AlignmentUtils
    * @param unmapped
    * @return
    */
-  static Map<Integer, Map<SequenceI, Character>> buildMappedColumnsMap(
+  static SortedMap<Integer, Map<SequenceI, Character>> buildMappedColumnsMap(
           AlignmentI unaligned, AlignmentI aligned, List<SequenceI> unmapped)
   {
     /*
@@ -2848,7 +2849,7 @@ public class AlignmentUtils
      * {unalignedSequence, characterPerSequence} at that position.
      * TreeMap keeps the entries in ascending column order. 
      */
-    Map<Integer, Map<SequenceI, Character>> map = new TreeMap<Integer, Map<SequenceI, Character>>();
+    SortedMap<Integer, Map<SequenceI, Character>> map = new TreeMap<Integer, Map<SequenceI, Character>>();
 
     /*
      * record any sequences that have no mapping so can't be realigned
index 7b9da46..565924b 100755 (executable)
@@ -33,6 +33,7 @@ import java.awt.Color;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.SortedMap;
 import java.util.TreeMap;
 import java.util.Vector;
 
@@ -243,7 +244,7 @@ public class Conservation
        * or not conserved (-1)
        * Using TreeMap means properties are displayed in alphabetical order
        */
-      Map<String, Integer> resultHash = new TreeMap<String, Integer>();
+      SortedMap<String, Integer> resultHash = new TreeMap<String, Integer>();
       SymbolCounts symbolCounts = values.getSymbolCounts();
       char[] symbols = symbolCounts.symbols;
       int[] counts = symbolCounts.values;
@@ -518,7 +519,7 @@ public class Conservation
    * 
    * @return Conservation sequence
    */
-  public Sequence getConsSequence()
+  public SequenceI getConsSequence()
   {
     return consSequence;
   }
index 72542b3..2802684 100644 (file)
@@ -31,6 +31,7 @@ import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.renderer.ResidueShaderI;
 import jalview.schemes.ColourSchemeI;
 
 import java.awt.Color;
@@ -79,6 +80,14 @@ public interface AlignViewportI extends ViewStyleI
 
   ColourSchemeI getGlobalColourScheme();
 
+  /**
+   * Returns an object that describes colouring (including any thresholding or
+   * fading) of the alignment
+   * 
+   * @return
+   */
+  ResidueShaderI getResidueShading();
+
   AlignmentI getAlignment();
 
   ColumnSelection getColumnSelection();
@@ -157,7 +166,7 @@ public interface AlignViewportI extends ViewStyleI
 
   /**
    * 
-   * @return the alignment annotatino row for the structure consensus
+   * @return the alignment annotation row for the structure consensus
    *         calculation
    */
   AlignmentAnnotation getAlignmentStrucConsensusAnnotation();
@@ -170,11 +179,13 @@ public interface AlignViewportI extends ViewStyleI
   void setRnaStructureConsensusHash(Hashtable[] hStrucConsensus);
 
   /**
-   * set global colourscheme
+   * Sets the colour scheme for the background alignment (as distinct from
+   * sub-groups, which may have their own colour schemes). A null value is used
+   * for no residue colour (white).
    * 
-   * @param rhc
+   * @param cs
    */
-  void setGlobalColourScheme(ColourSchemeI rhc);
+  void setGlobalColourScheme(ColourSchemeI cs);
 
   Map<SequenceI, SequenceCollectionI> getHiddenRepSequences();
 
index bf985d7..055fcf3 100644 (file)
@@ -39,13 +39,17 @@ import jalview.io.DataSourceType;
 import jalview.io.FileFormatI;
 import jalview.io.FileFormats;
 import jalview.io.SequenceAnnotationReport;
+import jalview.renderer.ResidueShader;
+import jalview.renderer.ResidueShaderI;
 import jalview.schemes.Blosum62ColourScheme;
 import jalview.schemes.BuriedColourScheme;
 import jalview.schemes.ClustalxColourScheme;
 import jalview.schemes.HelixColourScheme;
 import jalview.schemes.HydrophobicColourScheme;
+import jalview.schemes.JalviewColourScheme;
 import jalview.schemes.NucleotideColourScheme;
 import jalview.schemes.PIDColourScheme;
+import jalview.schemes.PurinePyrimidineColourScheme;
 import jalview.schemes.StrandColourScheme;
 import jalview.schemes.TaylorColourScheme;
 import jalview.schemes.TurnColourScheme;
@@ -67,6 +71,7 @@ import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.SortedMap;
 import java.util.TreeMap;
 import java.util.Vector;
 
@@ -77,46 +82,50 @@ public class APopupMenu extends java.awt.PopupMenu implements
 
   MenuItem editGroupName = new MenuItem();
 
-  protected MenuItem clustalColour = new MenuItem();
+  CheckboxMenuItem noColour = new CheckboxMenuItem();
 
-  protected MenuItem zappoColour = new MenuItem();
+  protected CheckboxMenuItem clustalColour = new CheckboxMenuItem();
 
-  protected MenuItem taylorColour = new MenuItem();
+  protected CheckboxMenuItem zappoColour = new CheckboxMenuItem();
 
-  protected MenuItem hydrophobicityColour = new MenuItem();
+  protected CheckboxMenuItem taylorColour = new CheckboxMenuItem();
 
-  protected MenuItem helixColour = new MenuItem();
+  protected CheckboxMenuItem hydrophobicityColour = new CheckboxMenuItem();
 
-  protected MenuItem strandColour = new MenuItem();
+  protected CheckboxMenuItem helixColour = new CheckboxMenuItem();
 
-  protected MenuItem turnColour = new MenuItem();
+  protected CheckboxMenuItem strandColour = new CheckboxMenuItem();
 
-  protected MenuItem buriedColour = new MenuItem();
+  protected CheckboxMenuItem turnColour = new CheckboxMenuItem();
 
-  protected MenuItem userDefinedColour = new MenuItem();
+  protected CheckboxMenuItem buriedColour = new CheckboxMenuItem();
 
-  protected MenuItem PIDColour = new MenuItem();
+  protected CheckboxMenuItem PIDColour = new CheckboxMenuItem();
 
-  protected MenuItem BLOSUM62Colour = new MenuItem();
+  protected CheckboxMenuItem BLOSUM62Colour = new CheckboxMenuItem();
 
-  MenuItem noColourmenuItem = new MenuItem();
+  CheckboxMenuItem nucleotideColour = new CheckboxMenuItem();
+
+  CheckboxMenuItem purinePyrimidineColour = new CheckboxMenuItem();
+
+  protected MenuItem userDefinedColour = new MenuItem();
 
   protected CheckboxMenuItem abovePIDColour = new CheckboxMenuItem();
 
   MenuItem modifyPID = new MenuItem();
 
-  protected CheckboxMenuItem conservationMenuItem = new CheckboxMenuItem();
+  protected CheckboxMenuItem conservationColour = new CheckboxMenuItem();
 
   MenuItem modifyConservation = new MenuItem();
 
+  MenuItem noColourmenuItem = new MenuItem();
+
   final AlignmentPanel ap;
 
   MenuItem unGroupMenuItem = new MenuItem();
 
   MenuItem createGroupMenuItem = new MenuItem();
 
-  MenuItem nucleotideMenuItem = new MenuItem();
-
   Menu colourMenu = new Menu();
 
   CheckboxMenuItem showBoxes = new CheckboxMenuItem();
@@ -234,6 +243,24 @@ public class APopupMenu extends java.awt.PopupMenu implements
     SequenceGroup sg = ap.av.getSelectionGroup();
     if (sg != null && sg.getSize() > 0)
     {
+      if (sg.isNucleotide())
+      {
+        conservationColour.setEnabled(false);
+        clustalColour.setEnabled(false);
+        BLOSUM62Colour.setEnabled(false);
+        zappoColour.setEnabled(false);
+        taylorColour.setEnabled(false);
+        hydrophobicityColour.setEnabled(false);
+        helixColour.setEnabled(false);
+        strandColour.setEnabled(false);
+        turnColour.setEnabled(false);
+        buriedColour.setEnabled(false);
+      }
+      else
+      {
+        purinePyrimidineColour.setEnabled(false);
+        nucleotideColour.setEnabled(false);
+      }
       editGroupName.setLabel(MessageManager.formatMessage(
               "label.name_param", new Object[] { sg.getName() }));
       showText.setState(sg.getDisplayText());
@@ -252,11 +279,12 @@ public class APopupMenu extends java.awt.PopupMenu implements
         if (sg.cs != null)
         {
           abovePIDColour.setState(sg.cs.getThreshold() > 0);
+          conservationColour.setState(sg.cs.conservationApplied());
           modifyPID.setEnabled(abovePIDColour.getState());
-          conservationMenuItem.setState(sg.cs.conservationApplied());
-          modifyConservation.setEnabled(conservationMenuItem.getState());
+          modifyConservation.setEnabled(conservationColour.getState());
         }
       }
+      setSelectedColour(sg.cs);
     }
     else
     {
@@ -314,6 +342,36 @@ public class APopupMenu extends java.awt.PopupMenu implements
   }
 
   /**
+   * Select the menu item (if any) matching the current colour scheme. This
+   * works by matching the menu item name (not display text) to the canonical
+   * name of the colour scheme.
+   * 
+   * @param cs
+   */
+  protected void setSelectedColour(ResidueShaderI cs)
+  {
+    if (cs == null || cs.getColourScheme() == null)
+    {
+      noColour.setState(true);
+    }
+    else
+    {
+      String name = cs.getColourScheme().getSchemeName();
+      for (int i = 0; i < colourMenu.getItemCount(); i++)
+      {
+        MenuItem item = colourMenu.getItem(i);
+        if (item instanceof CheckboxMenuItem)
+        {
+          if (name.equals(item.getName()))
+          {
+            ((CheckboxMenuItem) item).setState(true);
+          }
+        }
+      }
+    }
+  }
+
+  /**
    * Adds a 'Link' menu item with a sub-menu item for each hyperlink provided.
    * 
    * @param seq
@@ -423,7 +481,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
      * Temporary store to hold distinct calcId / type pairs for the tooltip.
      * Using TreeMap means calcIds are shown in alphabetical order.
      */
-    Map<String, String> tipEntries = new TreeMap<String, String>();
+    SortedMap<String, String> tipEntries = new TreeMap<String, String>();
     final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<SequenceI, List<AlignmentAnnotation>>();
     AlignmentI al = this.ap.av.getAlignment();
     AlignmentUtils.findAddableReferenceAnnotations(forSequences,
@@ -508,43 +566,28 @@ public class APopupMenu extends java.awt.PopupMenu implements
     linkMenu.add(item);
   }
 
+  /**
+   * Actions on selecting / unselecting a checkbox menu item
+   */
   @Override
   public void itemStateChanged(ItemEvent evt)
   {
     Object source = evt.getSource();
-    if (source == abovePIDColour)
+    if (source == noColour)
     {
-      abovePIDColour_itemStateChanged();
-    }
-    else if (source == conservationMenuItem)
-    {
-      conservationMenuItem_itemStateChanged();
-    }
-    else if (source == showColourText)
-    {
-      showColourText_itemStateChanged();
-    }
-    else if (source == showText)
-    {
-      showText_itemStateChanged();
+      noColourmenuItem_actionPerformed();
     }
-    else if (source == showBoxes)
+    else if (source == clustalColour)
     {
-      showBoxes_itemStateChanged();
+      clustalColour_actionPerformed();
     }
-    else if (source == displayNonconserved)
+    else if (source == BLOSUM62Colour)
     {
-      this.showNonconserved_itemStateChanged();
+      BLOSUM62Colour_actionPerformed();
     }
-  }
-
-  @Override
-  public void actionPerformed(ActionEvent evt)
-  {
-    Object source = evt.getSource();
-    if (source == clustalColour)
+    else if (evt.getSource() == PIDColour)
     {
-      clustalColour_actionPerformed();
+      PIDColour_actionPerformed();
     }
     else if (source == zappoColour)
     {
@@ -574,26 +617,50 @@ public class APopupMenu extends java.awt.PopupMenu implements
     {
       buriedColour_actionPerformed();
     }
-    else if (source == nucleotideMenuItem)
+    else if (source == nucleotideColour)
     {
       nucleotideMenuItem_actionPerformed();
     }
-
-    else if (source == userDefinedColour)
+    else if (source == purinePyrimidineColour)
     {
-      userDefinedColour_actionPerformed();
+      purinePyrimidineColour_actionPerformed();
     }
-    else if (source == PIDColour)
+    else if (source == abovePIDColour)
     {
-      PIDColour_actionPerformed();
+      abovePIDColour_itemStateChanged();
     }
-    else if (source == BLOSUM62Colour)
+    else if (source == conservationColour)
     {
-      BLOSUM62Colour_actionPerformed();
+      conservationMenuItem_itemStateChanged();
     }
-    else if (source == noColourmenuItem)
+    else if (source == showColourText)
     {
-      noColourmenuItem_actionPerformed();
+      showColourText_itemStateChanged();
+    }
+    else if (source == showText)
+    {
+      showText_itemStateChanged();
+    }
+    else if (source == showBoxes)
+    {
+      showBoxes_itemStateChanged();
+    }
+    else if (source == displayNonconserved)
+    {
+      this.showNonconserved_itemStateChanged();
+    }
+  }
+
+  /**
+   * Actions on clicking a menu item
+   */
+  @Override
+  public void actionPerformed(ActionEvent evt)
+  {
+    Object source = evt.getSource();
+    if (source == userDefinedColour)
+    {
+      userDefinedColour_actionPerformed();
     }
     else if (source == modifyConservation)
     {
@@ -868,14 +935,14 @@ public class APopupMenu extends java.awt.PopupMenu implements
   void addPDB()
   {
     Vector<PDBEntry> pdbs = seq.getAllPDBEntries();
-    if (pdbs != null&& !pdbs.isEmpty())
+    if (pdbs != null && !pdbs.isEmpty())
     {
       PDBEntry entry = pdbs.firstElement();
 
       if (ap.av.applet.jmolAvailable)
       {
-        new jalview.appletgui.AppletJmol(entry, new SequenceI[] { seq },
-                null, ap, DataSourceType.URL);
+        new AppletJmol(entry, new SequenceI[] { seq }, null, ap,
+                DataSourceType.URL);
       }
       else
       {
@@ -891,7 +958,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
       cap.setPDBImport(seq);
       Frame frame = new Frame();
       frame.add(cap);
-      jalview.bin.JalviewLite.addFrame(frame, MessageManager.formatMessage(
+      JalviewLite.addFrame(frame, MessageManager.formatMessage(
               "label.paste_pdb_file_for_sequence",
               new Object[] { seq.getName() }), 400, 300);
     }
@@ -911,19 +978,8 @@ public class APopupMenu extends java.awt.PopupMenu implements
             .getString("action.create_group"));
     createGroupMenuItem.addActionListener(this);
 
-    nucleotideMenuItem.setLabel(MessageManager
-            .getString("label.nucleotide"));
-    nucleotideMenuItem.addActionListener(this);
-    conservationMenuItem.addItemListener(this);
-    abovePIDColour.addItemListener(this);
-    modifyPID.setLabel(MessageManager
-            .getString("label.modify_identity_threshold"));
-    modifyPID.addActionListener(this);
-    modifyConservation.setLabel(MessageManager
-            .getString("label.modify_conservation_threshold"));
     modifyPID.setEnabled(abovePIDColour.getState());
-    modifyConservation.setEnabled(conservationMenuItem.getState());
-    modifyConservation.addActionListener(this);
+    modifyConservation.setEnabled(conservationColour.getState());
     colourMenu.setLabel(MessageManager.getString("label.group_colour"));
     showBoxes.setLabel(MessageManager.getString("action.boxes"));
     showBoxes.setState(true);
@@ -932,7 +988,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
     sequenceDetails.addActionListener(this);
     selSeqDetails.addActionListener(this);
     displayNonconserved.setLabel(MessageManager
-            .getString("label.show_non_conversed"));
+            .getString("label.show_non_conserved"));
     displayNonconserved.setState(false);
     displayNonconserved.addItemListener(this);
     showText.setLabel(MessageManager.getString("action.text"));
@@ -964,7 +1020,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
     groupMenu.add(unGroupMenuItem);
     groupMenu.add(menu1);
 
-    colourMenu.add(noColourmenuItem);
+    colourMenu.add(noColour);
     colourMenu.add(clustalColour);
     colourMenu.add(BLOSUM62Colour);
     colourMenu.add(PIDColour);
@@ -975,50 +1031,91 @@ public class APopupMenu extends java.awt.PopupMenu implements
     colourMenu.add(strandColour);
     colourMenu.add(turnColour);
     colourMenu.add(buriedColour);
-    colourMenu.add(nucleotideMenuItem);
+    colourMenu.add(nucleotideColour);
+    colourMenu.add(purinePyrimidineColour);
     colourMenu.add(userDefinedColour);
     colourMenu.addSeparator();
-    colourMenu.add(conservationMenuItem);
+    colourMenu.add(conservationColour);
     colourMenu.add(modifyConservation);
     colourMenu.add(abovePIDColour);
     colourMenu.add(modifyPID);
 
-    noColourmenuItem.setLabel(MessageManager.getString("label.none"));
-    noColourmenuItem.addActionListener(this);
+    noColour.setLabel(MessageManager.getString("label.none"));
+    noColour.addItemListener(this);
 
+    /*
+     * setName allows setSelectedColour to do its thing
+     */
     clustalColour.setLabel(MessageManager
-            .getString("label.clustalx_colours"));
-    clustalColour.addActionListener(this);
-    zappoColour.setLabel(MessageManager.getString("label.zappo"));
-    zappoColour.addActionListener(this);
-    taylorColour.setLabel(MessageManager.getString("label.taylor"));
-    taylorColour.addActionListener(this);
+            .getString("label.colourScheme_clustal"));
+    clustalColour.setName(JalviewColourScheme.Clustal.toString());
+    clustalColour.addItemListener(this);
+    BLOSUM62Colour.setLabel(MessageManager
+            .getString("label.colourScheme_blosum62"));
+    BLOSUM62Colour.setName(JalviewColourScheme.Blosum62.toString());
+    BLOSUM62Colour.addItemListener(this);
+    PIDColour.setLabel(MessageManager
+            .getString("label.colourScheme_%_identity"));
+    PIDColour.setName(JalviewColourScheme.PID.toString());
+    PIDColour.addItemListener(this);
+    zappoColour.setLabel(MessageManager
+            .getString("label.colourScheme_zappo"));
+    zappoColour.setName(JalviewColourScheme.Zappo.toString());
+    zappoColour.addItemListener(this);
+    taylorColour.setLabel(MessageManager
+            .getString("label.colourScheme_taylor"));
+    taylorColour.setName(JalviewColourScheme.Taylor.toString());
+    taylorColour.addItemListener(this);
     hydrophobicityColour.setLabel(MessageManager
-            .getString("label.hydrophobicity"));
-    hydrophobicityColour.addActionListener(this);
-    helixColour
-            .setLabel(MessageManager.getString("label.helix_propensity"));
-    helixColour.addActionListener(this);
+            .getString("label.colourScheme_hydrophobic"));
+    hydrophobicityColour
+            .setName(JalviewColourScheme.Hydrophobic.toString());
+    hydrophobicityColour.addItemListener(this);
+    helixColour.setLabel(MessageManager
+            .getString("label.colourScheme_helix_propensity"));
+    helixColour.setName(JalviewColourScheme.Helix.toString());
+    helixColour.addItemListener(this);
     strandColour.setLabel(MessageManager
-            .getString("label.strand_propensity"));
-    strandColour.addActionListener(this);
-    turnColour.setLabel(MessageManager.getString("label.turn_propensity"));
-    turnColour.addActionListener(this);
-    buriedColour.setLabel(MessageManager.getString("label.buried_index"));
-    buriedColour.addActionListener(this);
-    abovePIDColour.setLabel(MessageManager
-            .getString("label.above_identity_percentage"));
+            .getString("label.colourScheme_strand_propensity"));
+    strandColour.setName(JalviewColourScheme.Strand.toString());
+    strandColour.addItemListener(this);
+    turnColour.setLabel(MessageManager
+            .getString("label.colourScheme_turn_propensity"));
+    turnColour.setName(JalviewColourScheme.Turn.toString());
+    turnColour.addItemListener(this);
+    buriedColour.setLabel(MessageManager
+            .getString("label.colourScheme_buried_index"));
+    buriedColour.setName(JalviewColourScheme.Buried.toString());
+    buriedColour.addItemListener(this);
+    nucleotideColour.setLabel(MessageManager
+            .getString("label.colourScheme_nucleotide"));
+    nucleotideColour.setName(JalviewColourScheme.Nucleotide.toString());
+    nucleotideColour.addItemListener(this);
+    purinePyrimidineColour.setLabel(MessageManager
+            .getString("label.colourScheme_purine/pyrimidine"));
+    purinePyrimidineColour.setName(JalviewColourScheme.PurinePyrimidine
+            .toString());
+    purinePyrimidineColour.addItemListener(this);
 
     userDefinedColour.setLabel(MessageManager
             .getString("action.user_defined"));
     userDefinedColour.addActionListener(this);
-    PIDColour.setLabel(MessageManager
-            .getString("label.percentage_identity"));
+
+    abovePIDColour.setLabel(MessageManager
+            .getString("label.above_identity_threshold"));
+    abovePIDColour.addItemListener(this);
+    modifyPID.setLabel(MessageManager
+            .getString("label.modify_identity_threshold"));
+    modifyPID.addActionListener(this);
+    conservationColour.setLabel(MessageManager
+            .getString("action.by_conservation"));
+    conservationColour.addItemListener(this);
+    modifyConservation.setLabel(MessageManager
+            .getString("label.modify_conservation_threshold"));
+    modifyConservation.addActionListener(this);
+
     PIDColour.addActionListener(this);
-    BLOSUM62Colour.setLabel("BLOSUM62");
     BLOSUM62Colour.addActionListener(this);
-    conservationMenuItem.setLabel(MessageManager
-            .getString("action.by_conservation"));
 
     editMenu.add(copy);
     copy.addActionListener(this);
@@ -1068,55 +1165,63 @@ public class APopupMenu extends java.awt.PopupMenu implements
   protected void clustalColour_actionPerformed()
   {
     SequenceGroup sg = getGroup();
-    sg.cs = new ClustalxColourScheme(sg, ap.av.getHiddenRepSequences());
+    sg.cs = new ResidueShader(new ClustalxColourScheme(sg,
+            ap.av.getHiddenRepSequences()));
     refresh();
   }
 
   protected void zappoColour_actionPerformed()
   {
-    getGroup().cs = new ZappoColourScheme();
+    getGroup().cs = new ResidueShader(new ZappoColourScheme());
     refresh();
   }
 
   protected void taylorColour_actionPerformed()
   {
-    getGroup().cs = new TaylorColourScheme();
+    getGroup().cs = new ResidueShader(new TaylorColourScheme());
     refresh();
   }
 
   protected void hydrophobicityColour_actionPerformed()
   {
-    getGroup().cs = new HydrophobicColourScheme();
+    getGroup().cs = new ResidueShader(new HydrophobicColourScheme());
     refresh();
   }
 
   protected void helixColour_actionPerformed()
   {
-    getGroup().cs = new HelixColourScheme();
+    getGroup().cs = new ResidueShader(new HelixColourScheme());
     refresh();
   }
 
   protected void strandColour_actionPerformed()
   {
-    getGroup().cs = new StrandColourScheme();
+    getGroup().cs = new ResidueShader(new StrandColourScheme());
     refresh();
   }
 
   protected void turnColour_actionPerformed()
   {
-    getGroup().cs = new TurnColourScheme();
+    getGroup().cs = new ResidueShader(new TurnColourScheme());
     refresh();
   }
 
   protected void buriedColour_actionPerformed()
   {
-    getGroup().cs = new BuriedColourScheme();
+    getGroup().cs = new ResidueShader(new BuriedColourScheme());
     refresh();
   }
 
   public void nucleotideMenuItem_actionPerformed()
   {
-    getGroup().cs = new NucleotideColourScheme();
+    getGroup().cs = new ResidueShader(new NucleotideColourScheme());
+    refresh();
+  }
+
+  public void purinePyrimidineColour_actionPerformed()
+  {
+    getGroup().cs = new ResidueShader(
+            new PurinePyrimidineColourScheme());
     refresh();
   }
 
@@ -1158,7 +1263,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
   protected void PIDColour_actionPerformed()
   {
     SequenceGroup sg = getGroup();
-    sg.cs = new PIDColourScheme();
+    sg.cs = new ResidueShader(new PIDColourScheme());
     sg.cs.setConsensus(AAFrequency.calculate(sg.getSequences(ap.av
             .getHiddenRepSequences()), 0, ap.av.getAlignment().getWidth()));
     refresh();
@@ -1168,7 +1273,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
   {
     SequenceGroup sg = getGroup();
 
-    sg.cs = new Blosum62ColourScheme();
+    sg.cs = new ResidueShader(new Blosum62ColourScheme());
 
     sg.cs.setConsensus(AAFrequency.calculate(sg.getSequences(ap.av
             .getHiddenRepSequences()), 0, ap.av.getAlignment().getWidth()));
@@ -1190,12 +1295,14 @@ public class APopupMenu extends java.awt.PopupMenu implements
       return;
     }
 
-    if (conservationMenuItem.getState())
+    if (conservationColour.getState())
     {
-      sg.cs.setConservation(Conservation.calculateConservation("Group", sg
+      Conservation conservation = Conservation.calculateConservation(
+              "Group", sg
               .getSequences(ap.av.getHiddenRepSequences()), 0, ap.av
               .getAlignment().getWidth(), false, ap.av.getConsPercGaps(),
-              false));
+              false);
+      sg.getGroupColourScheme().setConservation(conservation);
       SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
       SliderPanel.showConservationSlider();
     }
@@ -1205,7 +1312,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
       SliderPanel.hideConservationSlider();
       sg.cs.setConservation(null);
     }
-    modifyConservation.setEnabled(conservationMenuItem.getState());
+    modifyConservation.setEnabled(conservationColour.getState());
     refresh();
   }
 
index 2287979..6a0b390 100644 (file)
@@ -64,7 +64,7 @@ import jalview.schemes.HydrophobicColourScheme;
 import jalview.schemes.NucleotideColourScheme;
 import jalview.schemes.PIDColourScheme;
 import jalview.schemes.PurinePyrimidineColourScheme;
-import jalview.schemes.RNAHelicesColourChooser;
+import jalview.schemes.RNAHelicesColour;
 import jalview.schemes.StrandColourScheme;
 import jalview.schemes.TCoffeeColourScheme;
 import jalview.schemes.TaylorColourScheme;
@@ -284,6 +284,16 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     }
     if (viewport.getAlignment().isNucleotide())
     {
+      conservationMenuItem.setEnabled(false);
+      clustalColour.setEnabled(false);
+      BLOSUM62Colour.setEnabled(false);
+      zappoColour.setEnabled(false);
+      taylorColour.setEnabled(false);
+      hydrophobicityColour.setEnabled(false);
+      helixColour.setEnabled(false);
+      strandColour.setEnabled(false);
+      turnColour.setEnabled(false);
+      buriedColour.setEnabled(false);
       viewport.updateStrucConsensus(alignPanel);
       if (viewport.getAlignment().hasRNAStructure())
       {
@@ -298,6 +308,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     {
       RNAHelixColour.setEnabled(false);
       purinePyrimidineColour.setEnabled(false);
+      nucleotideColour.setEnabled(false);
     }
     // Some JVMS send keyevents to Top frame or lowest panel,
     // Havent worked out why yet. So add to both this frame and seqCanvas for
@@ -1257,7 +1268,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     // }
     else if (source == RNAHelixColour)
     {
-      new RNAHelicesColourChooser(viewport, alignPanel);
+      changeColour(new RNAHelicesColour(viewport.getAlignment()));
+      // new RNAHelicesColourChooser(viewport, alignPanel);
     }
     else if (source == modifyPID)
     {
@@ -2629,26 +2641,6 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
   @Override
   public void changeColour(ColourSchemeI cs)
   {
-
-    if (cs != null)
-    {
-      if (viewport.getAbovePIDThreshold())
-      {
-        viewport.setThreshold(SliderPanel.setPIDSliderSource(alignPanel,
-                cs, "Background"));
-      }
-
-      if (viewport.getConservationSelected())
-      {
-        cs.setConservationApplied(true);
-        viewport.setIncrement(SliderPanel.setConservationSlider(alignPanel,
-                cs, "Background"));
-      }
-      else
-      {
-        cs.setConservationApplied(false);
-      }
-    }
     viewport.setGlobalColourScheme(cs);
 
     alignPanel.paintAlignment(true);
@@ -2660,7 +2652,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
             && viewport.getGlobalColourScheme() != null)
     {
       SliderPanel.setPIDSliderSource(alignPanel,
-              viewport.getGlobalColourScheme(), "Background");
+              viewport.getResidueShading(), alignPanel.getViewName());
       SliderPanel.showPIDSlider();
     }
   }
@@ -2671,7 +2663,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
             && viewport.getGlobalColourScheme() != null)
     {
       SliderPanel.setConservationSlider(alignPanel,
-              viewport.getGlobalColourScheme(), "Background");
+              viewport.getResidueShading(), alignPanel.getViewName());
       SliderPanel.showConservationSlider();
     }
   }
@@ -3459,7 +3451,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
             .getString("label.colour_text"));
     colourTextMenuItem.addItemListener(this);
     displayNonconservedMenuItem.setLabel(MessageManager
-            .getString("label.show_non_conversed"));
+            .getString("label.show_non_conserved"));
     displayNonconservedMenuItem.addItemListener(this);
     wrapMenuItem.setLabel(MessageManager.getString("action.wrap"));
     wrapMenuItem.addItemListener(this);
@@ -3482,45 +3474,50 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
             .getString("label.apply_colour_to_all_groups"));
     applyToAllGroups.setState(true);
     applyToAllGroups.addItemListener(this);
-    clustalColour.setLabel(MessageManager.getString("label.clustalx"));
+    clustalColour.setLabel(MessageManager
+            .getString("label.colourScheme_clustal"));
     clustalColour.addActionListener(this);
-    zappoColour.setLabel(MessageManager.getString("label.zappo"));
+    zappoColour.setLabel(MessageManager
+            .getString("label.colourScheme_zappo"));
     zappoColour.addActionListener(this);
-    taylorColour.setLabel(MessageManager.getString("label.taylor"));
+    taylorColour.setLabel(MessageManager
+            .getString("label.colourScheme_taylor"));
     taylorColour.addActionListener(this);
     hydrophobicityColour.setLabel(MessageManager
-            .getString("label.hydrophobicity"));
+            .getString("label.colourScheme_hydrophobic"));
     hydrophobicityColour.addActionListener(this);
-    helixColour
-            .setLabel(MessageManager.getString("label.helix_propensity"));
+    helixColour.setLabel(MessageManager
+            .getString("label.colourScheme_helix_propensity"));
     helixColour.addActionListener(this);
     strandColour.setLabel(MessageManager
-            .getString("label.strand_propensity"));
+            .getString("label.colourScheme_strand_propensity"));
     strandColour.addActionListener(this);
-    turnColour.setLabel(MessageManager.getString("label.turn_propensity"));
+    turnColour.setLabel(MessageManager
+            .getString("label.colourScheme_turn_propensity"));
     turnColour.addActionListener(this);
-    buriedColour.setLabel(MessageManager.getString("label.buried_index"));
+    buriedColour.setLabel(MessageManager
+            .getString("label.colourScheme_buried_index"));
     buriedColour.addActionListener(this);
     purinePyrimidineColour.setLabel(MessageManager
-            .getString("label.purine_pyrimidine"));
+            .getString("label.colourScheme_purine/pyrimidine"));
     purinePyrimidineColour.addActionListener(this);
     // RNAInteractionColour.setLabel(MessageManager
     // .getString("label.rna_interaction"));
     // RNAInteractionColour.addActionListener(this);
     RNAHelixColour.setLabel(MessageManager
-            .getString("action.by_rna_helixes"));
+            .getString("label.colourScheme_rna_helices"));
     RNAHelixColour.addActionListener(this);
     userDefinedColour.setLabel(MessageManager
             .getString("action.user_defined"));
     userDefinedColour.addActionListener(this);
     PIDColour.setLabel(MessageManager
-            .getString("label.percentage_identity"));
+            .getString("label.colourScheme_%_identity"));
     PIDColour.addActionListener(this);
     BLOSUM62Colour.setLabel(MessageManager
-            .getString("label.blosum62_score"));
+            .getString("label.colourScheme_blosum62"));
     BLOSUM62Colour.addActionListener(this);
-    tcoffeeColour
-            .setLabel(MessageManager.getString("label.tcoffee_scores"));
+    tcoffeeColour.setLabel(MessageManager
+            .getString("label.colourScheme_t-coffee_scores"));
     // it will be enabled only if a score file is provided
     tcoffeeColour.setEnabled(false);
     tcoffeeColour.addActionListener(this);
@@ -3532,7 +3529,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     abovePIDThreshold.setLabel(MessageManager
             .getString("label.above_identity_threshold"));
     abovePIDThreshold.addItemListener(this);
-    nucleotideColour.setLabel(MessageManager.getString("label.nucleotide"));
+    nucleotideColour.setLabel(MessageManager
+            .getString("label.colourScheme_nucleotide"));
     nucleotideColour.addActionListener(this);
     modifyPID.setLabel(MessageManager
             .getString("label.modify_identity_threshold"));
@@ -3574,7 +3572,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
             .getString("label.neighbour_joining_identity"));
     neighbourTreeMenuItem.addActionListener(this);
     avDistanceTreeBlosumMenuItem.setLabel(MessageManager
-            .getString("label.average_distance_bloslum62"));
+            .getString("label.average_distance_blosum62"));
     avDistanceTreeBlosumMenuItem.addActionListener(this);
     njTreeBlosumMenuItem.setLabel(MessageManager
             .getString("label.neighbour_blosum62"));
index 4bd77b6..fc087c6 100644 (file)
@@ -32,6 +32,7 @@ import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.renderer.ResidueShader;
 import jalview.schemes.ColourSchemeProperty;
 import jalview.schemes.UserColourScheme;
 import jalview.structure.CommandListener;
@@ -208,18 +209,19 @@ public class AlignViewport extends AlignmentViewport implements
 
       if (colour != null)
       {
-        globalColourScheme = ColourSchemeProperty.getColour(alignment,
-                colour);
-        if (globalColourScheme != null)
+        residueShading = new ResidueShader(
+                ColourSchemeProperty.getColourScheme(alignment, colour));
+        if (residueShading != null)
         {
-          globalColourScheme.setConsensus(hconsensus);
+          residueShading.setConsensus(hconsensus);
         }
       }
 
       if (applet.getParameter("userDefinedColour") != null)
       {
-        ((UserColourScheme) globalColourScheme).parseAppletParameter(applet
-                .getParameter("userDefinedColour"));
+        residueShading = new ResidueShader(
+                new UserColourScheme(
+                        applet.getParameter("userDefinedColour")));
       }
     }
     initAutoAnnotation();
index 79d2f1f..487b75c 100644 (file)
@@ -81,9 +81,9 @@ public class AnnotationColourChooser extends Panel implements
       oldgroupColours = new Hashtable();
       for (SequenceGroup sg : ap.av.getAlignment().getGroups())
       {
-        if (sg.cs != null)
+        if (sg.getColourScheme() != null)
         {
-          oldgroupColours.put(sg, sg.cs);
+          oldgroupColours.put(sg, sg.getColourScheme());
         }
         else
         {
@@ -487,8 +487,6 @@ public class AnnotationColourChooser extends Panel implements
     AnnotationColourGradient acg = null;
     if (currentColours.getState())
     {
-      acg = new AnnotationColourGradient(currentAnnotation,
-              av.getGlobalColourScheme(), aboveThreshold);
     }
     else
     {
@@ -513,21 +511,21 @@ public class AnnotationColourChooser extends Panel implements
       for (SequenceGroup sg : ap.av.getAlignment().getGroups())
       {
 
-        if (sg.cs == null)
+        if (sg.getColourScheme() == null)
         {
           continue;
         }
 
         if (currentColours.getState())
         {
-          sg.cs = new AnnotationColourGradient(currentAnnotation, sg.cs,
-                  aboveThreshold);
+          sg.setColourScheme(new AnnotationColourGradient(
+                  currentAnnotation, sg.getColourScheme(), aboveThreshold));
         }
         else
         {
-          sg.cs = new AnnotationColourGradient(currentAnnotation,
-                  minColour.getBackground(), maxColour.getBackground(),
-                  aboveThreshold);
+          sg.setColourScheme(new AnnotationColourGradient(
+                  currentAnnotation, minColour.getBackground(), maxColour
+                          .getBackground(), aboveThreshold));
         }
 
       }
@@ -548,12 +546,12 @@ public class AnnotationColourChooser extends Panel implements
         Object cs = oldgroupColours.get(sg);
         if (cs instanceof ColourSchemeI)
         {
-          sg.cs = (ColourSchemeI) cs;
+          sg.setColourScheme((ColourSchemeI) cs);
         }
         else
         {
           // probably the "null" string we set it to if it was null originally.
-          sg.cs = null;
+          sg.setColourScheme(null);
         }
       }
     }
index 9d4779c..c0b4ff0 100644 (file)
@@ -24,8 +24,8 @@ import jalview.bin.JalviewLite;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
-import jalview.io.FileParse;
 import jalview.io.DataSourceType;
+import jalview.io.FileParse;
 import jalview.io.StructureFile;
 import jalview.schemes.BuriedColourScheme;
 import jalview.schemes.HelixColourScheme;
@@ -93,27 +93,29 @@ public class AppletJmol extends EmbmenuFrame implements
   MenuItem charge = new MenuItem(
           MessageManager.getString("label.charge_cysteine"));
 
-  MenuItem zappo = new MenuItem(MessageManager.getString("label.zappo"));
+  MenuItem zappo = new MenuItem(
+          MessageManager.getString("label.colourScheme_zappo"));
 
-  MenuItem taylor = new MenuItem(MessageManager.getString("label.taylor"));
+  MenuItem taylor = new MenuItem(
+          MessageManager.getString("label.colourScheme_taylor"));
 
   MenuItem hydro = new MenuItem(
-          MessageManager.getString("label.hydrophobicity"));
+          MessageManager.getString("label.colourScheme_hydrophobic"));
 
   MenuItem helix = new MenuItem(
-          MessageManager.getString("label.helix_propensity"));
+          MessageManager.getString("label.colourScheme_helix_propensity"));
 
   MenuItem strand = new MenuItem(
-          MessageManager.getString("label.strand_propensity"));
+          MessageManager.getString("label.colourScheme_strand_propensity"));
 
   MenuItem turn = new MenuItem(
-          MessageManager.getString("label.turn_propensity"));
+          MessageManager.getString("label.colourScheme_turn_propensity"));
 
   MenuItem buried = new MenuItem(
-          MessageManager.getString("label.buried_index"));
+          MessageManager.getString("label.colourScheme_buried_index"));
 
   MenuItem purinepyrimidine = new MenuItem(
-          MessageManager.getString("label.purine_pyrimidine"));
+          MessageManager.getString("label.colourScheme_purine/pyrimidine"));
 
   MenuItem user = new MenuItem(
           MessageManager.getString("label.user_defined_colours"));
@@ -584,7 +586,7 @@ public class AppletJmol extends EmbmenuFrame implements
 
   public void updateTitleAndMenus()
   {
-    if (jmb.fileLoadingError != null && jmb.fileLoadingError.length() > 0)
+    if (jmb.hasFileLoadingError())
     {
       repaint();
       return;
index 2fca07d..67ca8e9 100644 (file)
@@ -27,7 +27,7 @@ import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.io.FeaturesFile;
 import jalview.schemes.FeatureColour;
-import jalview.schemes.UserColourScheme;
+import jalview.util.ColorUtils;
 import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
 
@@ -236,7 +236,7 @@ public class FeatureRenderer extends
           FeatureColourI col = getFeatureStyle(name.getText());
           if (col == null)
           {
-            Color generatedColour = UserColourScheme
+            Color generatedColour = ColorUtils
                     .createColourFromName(name.getText());
             col = new FeatureColour(generatedColour);
           }
index 1debda8..8cfd2dc 100644 (file)
@@ -1505,13 +1505,13 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
       if (av.getConservationSelected())
       {
-        SliderPanel.setConservationSlider(ap, av.getGlobalColourScheme(),
-                "Background");
+        SliderPanel.setConservationSlider(ap, av.getResidueShading(),
+                ap.getViewName());
       }
       if (av.getAbovePIDThreshold())
       {
-        SliderPanel.setPIDSliderSource(ap, av.getGlobalColourScheme(),
-                "Background");
+        SliderPanel.setPIDSliderSource(ap, av.getResidueShading(),
+                ap.getViewName());
       }
 
     }
index 970d20e..86d1f98 100755 (executable)
@@ -23,7 +23,7 @@ package jalview.appletgui;
 import jalview.api.FeatureRenderer;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
-import jalview.schemes.ColourSchemeI;
+import jalview.renderer.ResidueShaderI;
 
 import java.awt.Color;
 import java.awt.Font;
@@ -78,12 +78,12 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
     {
       if (currentSequenceGroup.getDisplayBoxes())
       {
-        getBoxColour(currentSequenceGroup.cs, seq, i);
+        getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq, i);
       }
     }
     else if (av.getShowBoxes())
     {
-      getBoxColour(av.getGlobalColourScheme(), seq, i);
+      getBoxColour(av.getResidueShading(), seq, i);
     }
 
     return resBoxColour;
@@ -114,11 +114,11 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
     return col;
   }
 
-  void getBoxColour(ColourSchemeI cs, SequenceI seq, int i)
+  void getBoxColour(ResidueShaderI shader, SequenceI seq, int i)
   {
-    if (cs != null)
+    if (shader != null)
     {
-      resBoxColour = cs.findColour(seq.getCharAt(i), i, seq);
+      resBoxColour = shader.findColour(seq.getCharAt(i), i, seq);
     }
     else if (forOverview
             && !jalview.util.Comparison.isGap(seq.getCharAt(i)))
@@ -176,12 +176,13 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
         {
           if (currentSequenceGroup.getDisplayBoxes())
           {
-            getBoxColour(currentSequenceGroup.cs, seq, i);
+            getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq,
+                    i);
           }
         }
         else if (av.getShowBoxes())
         {
-          getBoxColour(av.getGlobalColourScheme(), seq, i);
+          getBoxColour(av.getResidueShading(), seq, i);
         }
       }
 
@@ -254,7 +255,7 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
 
         if (currentSequenceGroup.getColourText())
         {
-          getBoxColour(currentSequenceGroup.cs, seq, i);
+          getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq, i);
           graphics.setColor(resBoxColour.darker());
         }
         if (currentSequenceGroup.getShowNonconserved())
@@ -271,7 +272,7 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
 
         if (av.getColourText())
         {
-          getBoxColour(av.getGlobalColourScheme(), seq, i);
+          getBoxColour(av.getResidueShading(), seq, i);
           if (av.getShowBoxes())
           {
             graphics.setColor(resBoxColour.darker());
index 3e6dbe6..9154aa0 100644 (file)
@@ -21,7 +21,7 @@
 package jalview.appletgui;
 
 import jalview.datamodel.SequenceGroup;
-import jalview.schemes.ColourSchemeI;
+import jalview.renderer.ResidueShaderI;
 import jalview.util.MessageManager;
 
 import java.awt.BorderLayout;
@@ -49,38 +49,39 @@ import java.util.Iterator;
 public class SliderPanel extends Panel implements ActionListener,
         AdjustmentListener, MouseListener
 {
+  private static final String BACKGROUND = "Background";
+
   AlignmentPanel ap;
 
   boolean forConservation = true;
 
-  ColourSchemeI cs;
+  ResidueShaderI cs;
 
   static Frame conservationSlider;
 
   static Frame PIDSlider;
 
   public static int setConservationSlider(AlignmentPanel ap,
-          ColourSchemeI cs, String source)
+          ResidueShaderI ccs, String source)
   {
     SliderPanel sp = null;
 
     if (conservationSlider == null)
     {
-      sp = new SliderPanel(ap, cs.getConservationInc(), true, cs);
+      sp = new SliderPanel(ap, ccs.getConservationInc(), true, ccs);
       conservationSlider = new Frame();
       conservationSlider.add(sp);
     }
     else
     {
       sp = (SliderPanel) conservationSlider.getComponent(0);
-      sp.valueField.setText(String.valueOf(cs.getConservationInc()));
-      sp.cs = cs;
+      sp.cs = ccs;
+      sp.valueField.setText(String.valueOf(ccs.getConservationInc()));
     }
 
-    conservationSlider
-            .setTitle(MessageManager.formatMessage(
-                    "label.conservation_colour_increment",
-                    new String[] { source }));
+    conservationSlider.setTitle(MessageManager.formatMessage(
+            "label.conservation_colour_increment",
+            new String[] { source == null ? BACKGROUND : source }));
     if (ap.av.getAlignment().getGroups() != null)
     {
       sp.setAllGroupsCheckEnabled(true);
@@ -120,26 +121,25 @@ public class SliderPanel extends Panel implements ActionListener,
 
   }
 
-  public static int setPIDSliderSource(AlignmentPanel ap, ColourSchemeI cs,
-          String source)
+  public static int setPIDSliderSource(AlignmentPanel ap,
+          ResidueShaderI ccs, String source)
   {
     SliderPanel pid = null;
     if (PIDSlider == null)
     {
-      pid = new SliderPanel(ap, cs.getThreshold(), false, cs);
+      pid = new SliderPanel(ap, ccs.getThreshold(), false, ccs);
       PIDSlider = new Frame();
       PIDSlider.add(pid);
     }
     else
     {
       pid = (SliderPanel) PIDSlider.getComponent(0);
-      pid.valueField.setText(String.valueOf(cs.getThreshold()));
-      pid.cs = cs;
+      pid.cs = ccs;
+      pid.valueField.setText(String.valueOf(ccs.getThreshold()));
     }
-    PIDSlider
-            .setTitle(MessageManager.formatMessage(
-                    "label.percentage_identity_threshold",
-                    new String[] { source }));
+    PIDSlider.setTitle(MessageManager.formatMessage(
+            "label.percentage_identity_threshold",
+            new String[] { source == null ? BACKGROUND : source }));
 
     if (ap.av.getAlignment().getGroups() != null)
     {
@@ -193,7 +193,7 @@ public class SliderPanel extends Panel implements ActionListener,
   }
 
   /**
-   * Hides the conservation slider panel if it is shown
+   * Hides the Conservation slider panel if it is shown
    */
   public static void hideConservationSlider()
   {
@@ -204,7 +204,7 @@ public class SliderPanel extends Panel implements ActionListener,
     }
   }
   public SliderPanel(AlignmentPanel ap, int value, boolean forConserve,
-          ColourSchemeI cs)
+          ResidueShaderI shader)
   {
     try
     {
@@ -214,7 +214,7 @@ public class SliderPanel extends Panel implements ActionListener,
       e.printStackTrace();
     }
     this.ap = ap;
-    this.cs = cs;
+    this.cs = shader;
     forConservation = forConserve;
     undoButton.setVisible(false);
     applyButton.setVisible(false);
@@ -249,7 +249,7 @@ public class SliderPanel extends Panel implements ActionListener,
       return;
     }
 
-    ColourSchemeI toChange = cs;
+    ResidueShaderI toChange = cs;
     Iterator<SequenceGroup> allGroups = null;
 
     if (allGroupsCheck.getState())
index 8292a5a..e30879c 100755 (executable)
@@ -656,35 +656,38 @@ public class TreeCanvas extends Panel implements MouseListener,
         }
         else
         {
-          cs = ColourSchemeProperty.getColour(sg, ColourSchemeProperty
-                  .getColourName(av.getGlobalColourScheme()));
+          cs = ColourSchemeProperty.getColourScheme(sg,
+                  ColourSchemeProperty.getColourName(av
+                          .getGlobalColourScheme()));
         }
         // cs is null if shading is an annotationColourGradient
-        if (cs != null)
-        {
-          cs.setThreshold(av.getGlobalColourScheme().getThreshold(),
-                  av.isIgnoreGapsConsensus());
-        }
+        // if (cs != null)
+        // {
+        // cs.setThreshold(av.getViewportColourScheme().getThreshold(),
+        // av.isIgnoreGapsConsensus());
+        // }
       }
       // TODO: cs used to be initialized with a sequence collection and
       // recalcConservation called automatically
       // instead we set it manually - recalc called after updateAnnotation
-      sg.cs = cs;
+      sg.setColourScheme(cs);
+      sg.getGroupColourScheme().setThreshold(
+              av.getResidueShading().getThreshold(),
+              av.isIgnoreGapsConsensus());
 
       sg.setName("JTreeGroup:" + sg.hashCode());
       sg.setIdColour(col);
       if (av.getGlobalColourScheme() != null
-              && av.getGlobalColourScheme().conservationApplied())
+              && av.getResidueShading().conservationApplied())
       {
         Conservation c = new Conservation("Group", sg.getSequences(null),
                 sg.getStartRes(), sg.getEndRes());
 
         c.calculate();
         c.verdict(false, av.getConsPercGaps());
-        cs.setConservation(c);
-
-        sg.cs = cs;
 
+        sg.setColourScheme(cs);
+        sg.getGroupColourScheme().setConservation(c);
       }
 
       av.getAlignment().addGroup(sg);
index 88098a9..95e36b5 100644 (file)
@@ -22,6 +22,7 @@ package jalview.appletgui;
 
 import jalview.api.FeatureColourI;
 import jalview.datamodel.SequenceGroup;
+import jalview.renderer.ResidueShader;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.FeatureColour;
 import jalview.schemes.ResidueProperties;
@@ -93,7 +94,7 @@ public class UserDefinedColours extends Panel implements ActionListener,
 
     if (seqGroup != null)
     {
-      oldColourScheme = seqGroup.cs;
+      oldColourScheme = seqGroup.getColourScheme();
     }
     else
     {
@@ -407,14 +408,9 @@ public class UserDefinedColours extends Panel implements ActionListener,
   {
     final Button button = new Button();
     Color col = Color.white;
-    if (oldColourScheme != null)
+    if (oldColourScheme != null && oldColourScheme.isSimple())
     {
-      try
-      {
-        col = oldColourScheme.findColour(aa.charAt(0), -1, null);
-      } catch (Exception ex)
-      {
-      }
+      col = oldColourScheme.findColour(aa.charAt(0), 0, null, null, 0f);
     }
     button.setBackground(col);
     oldColours.addElement(col);
@@ -501,20 +497,24 @@ public class UserDefinedColours extends Panel implements ActionListener,
     }
 
     UserColourScheme ucs = new UserColourScheme(newColours);
-    if (ap != null)
-    {
-      ucs.setThreshold(0, ap.av.isIgnoreGapsConsensus());
-    }
+    // if (ap != null)
+    // {
+    // ucs.setThreshold(0, ap.av.isIgnoreGapsConsensus());
+    // }
 
     if (ap != null)
     {
       if (seqGroup != null)
       {
-        seqGroup.cs = ucs;
+        seqGroup.cs = new ResidueShader(ucs);
+        seqGroup.getGroupColourScheme().setThreshold(0,
+                ap.av.isIgnoreGapsConsensus());
       }
       else
       {
         ap.av.setGlobalColourScheme(ucs);
+        ap.av.getResidueShading().setThreshold(0,
+                ap.av.isIgnoreGapsConsensus());
       }
       ap.seqPanel.seqCanvas.img = null;
       ap.paintAlignment(true);
@@ -592,7 +592,7 @@ public class UserDefinedColours extends Panel implements ActionListener,
     {
       if (seqGroup != null)
       {
-        seqGroup.cs = ucs;
+        seqGroup.cs = new ResidueShader(ucs);
       }
       else
       {
index 8412dab..9363c23 100755 (executable)
 package jalview.bin;
 
 import jalview.datamodel.PDBEntry;
+import jalview.gui.UserDefinedColours;
+import jalview.schemes.ColourSchemes;
+import jalview.schemes.UserColourScheme;
 import jalview.structure.StructureImportSettings;
+import jalview.util.ColorUtils;
 import jalview.ws.dbsources.das.api.DasSourceRegistryI;
 import jalview.ws.dbsources.das.datamodel.DasSourceRegistry;
 import jalview.ws.sifts.SiftsSettings;
@@ -40,6 +44,7 @@ import java.util.Date;
 import java.util.Enumeration;
 import java.util.Locale;
 import java.util.Properties;
+import java.util.StringTokenizer;
 import java.util.TreeSet;
 
 import org.apache.log4j.ConsoleAppender;
@@ -526,7 +531,7 @@ public class Cache
     setProperty("VERSION", codeVersion);
 
     // LOAD USERDEFINED COLOURS
-    jalview.gui.UserDefinedColours
+    jalview.bin.Cache
             .initUserColourSchemes(getProperty("USER_DEFINED_COLOURS"));
     jalview.io.PIRFile.useModellerOutput = Cache.getDefault("PIR_MODELLER",
             false);
@@ -868,19 +873,11 @@ public class Cache
     {
       return defcolour;
     }
-    Color col = jalview.schemes.ColourSchemeProperty
-            .getAWTColorFromName(colprop);
+    Color col = ColorUtils.parseColourString(colprop);
     if (col == null)
     {
-      try
-      {
-        col = new jalview.schemes.UserColourScheme(colprop).findColour('A');
-      } catch (Exception ex)
-      {
-        log.warn("Couldn't parse '" + colprop + "' as a colour for "
-                + property);
-        col = null;
-      }
+      log.warn("Couldn't parse '" + colprop + "' as a colour for "
+              + property);
     }
     return (col == null) ? defcolour : col;
   }
@@ -997,4 +994,54 @@ public class Cache
       Cache.applicationProperties.setProperty(propName, value);
     }
   }
+
+  /**
+   * Loads in user colour schemes from files.
+   * 
+   * @param files
+   *          a '|'-delimited list of file paths
+   */
+  public static void initUserColourSchemes(String files)
+  {
+    if (files == null || files.length() == 0)
+    {
+      return;
+    }
+  
+    // In case colours can't be loaded, we'll remove them
+    // from the default list here.
+    StringBuffer coloursFound = new StringBuffer();
+    StringTokenizer st = new StringTokenizer(files, "|");
+    while (st.hasMoreElements())
+    {
+      String file = st.nextToken();
+      try
+      {
+        UserColourScheme ucs = ColourSchemes.loadColourScheme(file);
+        if (ucs != null)
+        {
+          if (coloursFound.length() > 0)
+          {
+            coloursFound.append("|");
+          }
+          coloursFound.append(file);
+          ColourSchemes.getInstance().registerColourScheme(ucs);
+        }
+      } catch (Exception ex)
+      {
+        System.out.println("Error loading User ColourFile\n" + ex);
+      }
+    }
+    if (!files.equals(coloursFound.toString()))
+    {
+      if (coloursFound.toString().length() > 1)
+      {
+        setProperty(UserDefinedColours.USER_DEFINED_COLOURS, coloursFound.toString());
+      }
+      else
+      {
+        applicationProperties.remove(UserDefinedColours.USER_DEFINED_COLOURS);
+      }
+    }
+  }
 }
index 39c0a5b..966e952 100755 (executable)
@@ -40,7 +40,6 @@ import jalview.io.NewickFile;
 import jalview.io.gff.SequenceOntologyFactory;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemeProperty;
-import jalview.schemes.UserColourScheme;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 import jalview.ws.jws2.Jws2Discoverer;
@@ -511,16 +510,10 @@ public class Jalview
         {
           data.replaceAll("%20", " ");
 
-          ColourSchemeI cs = ColourSchemeProperty.getColour(af
+          ColourSchemeI cs = ColourSchemeProperty.getColourScheme(af
                   .getViewport().getAlignment(), data);
 
-          if (cs == null)
-          {
-            UserColourScheme ucs = new UserColourScheme("white");
-            ucs.parseAppletParameter(data);
-            cs = ucs;
-          }
-          else
+          if (cs != null)
           {
             System.out.println("CMD [-color " + data
                     + "] executed successfully!");
index d7b064a..7fa5147 100644 (file)
@@ -51,6 +51,7 @@ import jalview.javascript.JsCallBack;
 import jalview.javascript.MouseOverStructureListener;
 import jalview.structure.SelectionListener;
 import jalview.structure.StructureSelectionManager;
+import jalview.util.ColorUtils;
 import jalview.util.HttpUtils;
 import jalview.util.MessageManager;
 
@@ -2888,22 +2889,13 @@ public class JalviewLite extends Applet implements
     {
       return defcolour;
     }
-    Color col = jalview.schemes.ColourSchemeProperty
-            .getAWTColorFromName(colprop);
+    Color col = ColorUtils.parseColourString(colprop);
     if (col == null)
     {
-      try
-      {
-        col = new jalview.schemes.UserColourScheme(colprop).findColour('A');
-      } catch (Exception ex)
-      {
-        System.err.println("Couldn't parse '" + colprop
-                + "' as a colour for " + colparam);
-        col = null;
-      }
+      System.err.println("Couldn't parse '" + colprop
+              + "' as a colour for " + colparam);
     }
     return (col == null) ? defcolour : col;
-
   }
 
   public void openJalviewHelpUrl()
index 90bdcae..a6f2bf4 100755 (executable)
@@ -54,11 +54,7 @@ public class Alignment implements AlignmentI
 
   protected char gapCharacter = '-';
 
-  protected int type = NUCLEOTIDE;
-
-  public static final int PROTEIN = 0;
-
-  public static final int NUCLEOTIDE = 1;
+  private boolean nucleotide = true;
 
   public boolean hasRNAStructure = false;
 
@@ -76,14 +72,7 @@ public class Alignment implements AlignmentI
     hiddenSequences = new HiddenSequences(this);
     codonFrameList = new ArrayList<AlignedCodonFrame>();
 
-    if (Comparison.isNucleotide(seqs))
-    {
-      type = NUCLEOTIDE;
-    }
-    else
-    {
-      type = PROTEIN;
-    }
+    nucleotide = Comparison.isNucleotide(seqs);
 
     sequences = Collections.synchronizedList(new ArrayList<SequenceI>());
 
@@ -218,7 +207,9 @@ public class Alignment implements AlignmentI
   }
 
   /**
-   * Adds a sequence to the alignment. Recalculates maxLength and size.
+   * Adds a sequence to the alignment. Recalculates maxLength and size. Note
+   * this currently does not recalculate whether or not the alignment is
+   * nucleotide, so mixed alignments may have undefined behaviour.
    * 
    * @param snew
    */
@@ -978,29 +969,9 @@ public class Alignment implements AlignmentI
   }
 
   @Override
-  public void setNucleotide(boolean b)
-  {
-    if (b)
-    {
-      type = NUCLEOTIDE;
-    }
-    else
-    {
-      type = PROTEIN;
-    }
-  }
-
-  @Override
   public boolean isNucleotide()
   {
-    if (type == NUCLEOTIDE)
-    {
-      return true;
-    }
-    else
-    {
-      return false;
-    }
+    return nucleotide;
   }
 
   @Override
@@ -1591,7 +1562,6 @@ public class Alignment implements AlignmentI
           String calcId, boolean autoCalc, SequenceI seqRef,
           SequenceGroup groupRef)
   {
-    assert (name != null);
     if (annotations != null)
     {
       for (AlignmentAnnotation annot : getAlignmentAnnotation())
@@ -1623,14 +1593,18 @@ public class Alignment implements AlignmentI
   @Override
   public Iterable<AlignmentAnnotation> findAnnotation(String calcId)
   {
-    ArrayList<AlignmentAnnotation> aa = new ArrayList<AlignmentAnnotation>();
-    for (AlignmentAnnotation a : getAlignmentAnnotation())
+    List<AlignmentAnnotation> aa = new ArrayList<AlignmentAnnotation>();
+    AlignmentAnnotation[] alignmentAnnotation = getAlignmentAnnotation();
+    if (alignmentAnnotation != null)
     {
-      if (a.getCalcId() == calcId
-              || (a.getCalcId() != null && calcId != null && a.getCalcId()
-                      .equals(calcId)))
+      for (AlignmentAnnotation a : alignmentAnnotation)
       {
-        aa.add(a);
+        if (a.getCalcId() == calcId
+                || (a.getCalcId() != null && calcId != null && a
+                        .getCalcId().equals(calcId)))
+        {
+          aa.add(a);
+        }
       }
     }
     return aa;
index 2df099a..752235b 100755 (executable)
@@ -285,13 +285,6 @@ public interface AlignmentI extends AnnotatedCollectionI
   char getGapCharacter();
 
   /**
-   * Test for all nucleotide alignment
-   * 
-   * @return true if alignment is nucleotide sequence
-   */
-  boolean isNucleotide();
-
-  /**
    * Test if alignment contains RNA structure
    * 
    * @return true if RNA structure AligmnentAnnotation was added to alignment
@@ -299,12 +292,6 @@ public interface AlignmentI extends AnnotatedCollectionI
   boolean hasRNAStructure();
 
   /**
-   * Set alignment to be a nucleotide sequence
-   * 
-   */
-  void setNucleotide(boolean b);
-
-  /**
    * Get the associated dataset for the alignment.
    * 
    * @return Alignment containing dataset sequences or null of this is a
index 74568e4..3f6c515 100644 (file)
@@ -31,6 +31,13 @@ public interface AnnotatedCollectionI extends SequenceCollectionI
    */
   AlignmentAnnotation[] getAlignmentAnnotation();
 
+  /**
+   * Returns a list of annotations matching the given calc id, or an empty list
+   * if calcId is null
+   * 
+   * @param calcId
+   * @return
+   */
   Iterable<AlignmentAnnotation> findAnnotation(String calcId);
 
   Iterable<AlignmentAnnotation> findAnnotations(SequenceI seq,
index aca79c8..f681f11 100644 (file)
@@ -64,4 +64,10 @@ public interface SequenceCollectionI
    */
   int getEndRes();
 
+  /**
+   * Answers true if sequence data is nucleotide (according to some heuristic)
+   * 
+   * @return
+   */
+  boolean isNucleotide();
 }
index 9245761..4f9d530 100755 (executable)
@@ -22,6 +22,8 @@ package jalview.datamodel;
 
 import jalview.analysis.AAFrequency;
 import jalview.analysis.Conservation;
+import jalview.renderer.ResidueShader;
+import jalview.renderer.ResidueShaderI;
 import jalview.schemes.ColourSchemeI;
 
 import java.awt.Color;
@@ -69,7 +71,7 @@ public class SequenceGroup implements AnnotatedCollectionI
   /**
    * Colourscheme applied to group if any
    */
-  public ColourSchemeI cs;
+  public ResidueShaderI cs;
 
   // start column (base 0)
   int startRes = 0;
@@ -116,6 +118,7 @@ public class SequenceGroup implements AnnotatedCollectionI
   public SequenceGroup()
   {
     groupName = "JGroup:" + this.hashCode();
+    cs = new ResidueShader();
   }
 
   /**
@@ -136,12 +139,13 @@ public class SequenceGroup implements AnnotatedCollectionI
           ColourSchemeI scheme, boolean displayBoxes, boolean displayText,
           boolean colourText, int start, int end)
   {
+    this();
     this.sequences = sequences;
     this.groupName = groupName;
     this.displayBoxes = displayBoxes;
     this.displayText = displayText;
     this.colourText = colourText;
-    this.cs = scheme;
+    this.cs = new ResidueShader(scheme);
     startRes = start;
     endRes = end;
     recalcConservation();
@@ -154,6 +158,7 @@ public class SequenceGroup implements AnnotatedCollectionI
    */
   public SequenceGroup(SequenceGroup seqsel)
   {
+    this();
     if (seqsel != null)
     {
       sequences = new ArrayList<SequenceI>();
@@ -1269,10 +1274,14 @@ public class SequenceGroup implements AnnotatedCollectionI
   @Override
   public Iterable<AlignmentAnnotation> findAnnotation(String calcId)
   {
-    ArrayList<AlignmentAnnotation> aa = new ArrayList<AlignmentAnnotation>();
+    List<AlignmentAnnotation> aa = new ArrayList<AlignmentAnnotation>();
+    if (calcId == null)
+    {
+      return aa;
+    }
     for (AlignmentAnnotation a : getAlignmentAnnotation())
     {
-      if (a.getCalcId() == calcId)
+      if (calcId.equals(a.getCalcId()))
       {
         aa.add(a);
       }
@@ -1338,13 +1347,25 @@ public class SequenceGroup implements AnnotatedCollectionI
   private AnnotatedCollectionI context;
 
   /**
-   * set the alignment or group context for this group
+   * Sets the alignment or group context for this group
    * 
-   * @param context
+   * @param ctx
+   * @throws IllegalArgumentException
+   *           if setting the context would result in a circular reference chain
    */
-  public void setContext(AnnotatedCollectionI context)
+  public void setContext(AnnotatedCollectionI ctx)
   {
-    this.context = context;
+    AnnotatedCollectionI ref = ctx;
+    while (ref != null)
+    {
+      if (ref == this)
+      {
+        throw new IllegalArgumentException(
+                "Circular reference in SequenceGroup.context");
+      }
+      ref = ref.getContext();
+    }
+    this.context = ctx;
   }
 
   /*
@@ -1357,4 +1378,37 @@ public class SequenceGroup implements AnnotatedCollectionI
   {
     return context;
   }
+
+  public void setColourScheme(ColourSchemeI scheme)
+  {
+    if (cs == null)
+    {
+      cs = new ResidueShader();
+    }
+    cs.setColourScheme(scheme);
+  }
+
+  public void setGroupColourScheme(ResidueShaderI scheme)
+  {
+    cs = scheme;
+  }
+
+  public ColourSchemeI getColourScheme()
+  {
+    return cs == null ? null : cs.getColourScheme();
+  }
+
+  public ResidueShaderI getGroupColourScheme()
+  {
+    return cs;
+  }
+
+  @Override
+  public boolean isNucleotide()
+  {
+    if (context != null) {
+      return context.isNucleotide();
+    }
+    return false;
+  }
 }
index 2d2d10e..bf80831 100644 (file)
@@ -20,7 +20,6 @@
  */
 package jalview.ext.jmol;
 
-import jalview.api.AlignmentViewPanel;
 import jalview.api.FeatureRenderer;
 import jalview.api.SequenceRenderer;
 import jalview.datamodel.AlignmentI;
@@ -76,8 +75,6 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
 
   Hashtable<String, String> chainFile;
 
-  public String fileLoadingError;
-
   /*
    * the default or current model displayed if the model cannot be identified
    * from the selection message
@@ -171,6 +168,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     releaseUIResources();
   }
 
+  @Override
   public void colourByChain()
   {
     colourBySequence = false;
@@ -180,6 +178,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     evalStateCommand("select *;color chain");
   }
 
+  @Override
   public void colourByCharge()
   {
     colourBySequence = false;
@@ -241,6 +240,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
    * @param _hiddenCols
    *          an array of corresponding hidden columns for each alignment
    */
+  @Override
   public void superposeStructures(AlignmentI[] _alignment,
           int[] _refStructure, ColumnSelection[] _hiddenCols)
   {
@@ -487,35 +487,15 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   }
 
   /**
-   * colour any structures associated with sequences in the given alignment
-   * using the getFeatureRenderer() and getSequenceRenderer() renderers but only
-   * if colourBySequence is enabled.
+   * Sends a set of colour commands to the structure viewer
+   * 
+   * @param colourBySequenceCommands
    */
-  public void colourBySequence(AlignmentViewPanel alignmentv)
+  @Override
+  protected void colourBySequence(
+          StructureMappingcommandSet[] colourBySequenceCommands)
   {
-    boolean showFeatures = alignmentv.getAlignViewport()
-            .isShowSequenceFeatures();
-    if (!colourBySequence || !isLoadingFinished())
-    {
-      return;
-    }
-    if (getSsm() == null)
-    {
-      return;
-    }
-    String[] files = getPdbFile();
-
-    SequenceRenderer sr = getSequenceRenderer(alignmentv);
-
-    FeatureRenderer fr = null;
-    if (showFeatures)
-    {
-      fr = getFeatureRenderer(alignmentv);
-    }
-    AlignmentI alignment = alignmentv.getAlignment();
-
-    for (jalview.structure.StructureMappingcommandSet cpdbbyseq : getColourBySequenceCommands(
-            files, sr, fr, alignment))
+    for (StructureMappingcommandSet cpdbbyseq : colourBySequenceCommands)
     {
       for (String cbyseq : cpdbbyseq.commands)
       {
@@ -531,6 +511,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
    * @param alignment
    * @return
    */
+  @Override
   protected StructureMappingcommandSet[] getColourBySequenceCommands(
           String[] files, SequenceRenderer sr, FeatureRenderer fr,
           AlignmentI alignment)
@@ -598,17 +579,6 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   }
 
   /**
-   * returns the current featureRenderer that should be used to colour the
-   * structures
-   * 
-   * @param alignment
-   * 
-   * @return
-   */
-  public abstract FeatureRenderer getFeatureRenderer(
-          AlignmentViewPanel alignment);
-
-  /**
    * instruct the Jalview binding to update the pdbentries vector if necessary
    * prior to matching the jmol view's contents to the list of structure files
    * Jalview knows about.
@@ -717,16 +687,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     return null;
   }
 
-  /**
-   * returns the current sequenceRenderer that should be used to colour the
-   * structures
-   * 
-   * @param alignment
-   * 
-   * @return
-   */
-  public abstract SequenceRenderer getSequenceRenderer(
-          AlignmentViewPanel alignment);
+  
 
   // ///////////////////////////////
   // JmolStatusListener
@@ -1286,6 +1247,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
 
   }
 
+  @Override
   public void setJalviewColourScheme(ColourSchemeI cs)
   {
     colourBySequence = false;
@@ -1300,10 +1262,12 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     command.append("select *;color white;");
     List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
             false);
-    for (String res : residueSet)
+    for (String resName : residueSet)
     {
-      Color col = cs.findColour(res.charAt(0));
-      command.append("select " + res + ";color[" + col.getRed() + ","
+      char res = resName.length() == 3 ? ResidueProperties
+              .getSingleCharacterCode(resName) : resName.charAt(0);
+      Color col = cs.findColour(res, 0, null, null, 0f);
+      command.append("select " + resName + ";color[" + col.getRed() + ","
               + col.getGreen() + "," + col.getBlue() + "];");
     }
 
@@ -1400,6 +1364,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
 
   protected org.jmol.api.JmolAppConsoleInterface console = null;
 
+  @Override
   public void setBackgroundColour(java.awt.Color col)
   {
     jmolHistory(false);
index a551ca2..8f6b2f1 100644 (file)
@@ -35,6 +35,7 @@ import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.SortedMap;
 import java.util.TreeMap;
 
 /**
@@ -58,7 +59,7 @@ public class ChimeraCommands
           SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr,
           AlignmentI alignment)
   {
-    Map<Color, Map<Integer, Map<String, List<int[]>>>> colourMap = buildColoursMap(
+    Map<Color, SortedMap<Integer, Map<String, List<int[]>>>> colourMap = buildColoursMap(
             ssm, files, sequence, sr, fr, alignment);
 
     List<String> colourCommands = buildColourCommands(colourMap);
@@ -86,7 +87,7 @@ public class ChimeraCommands
    * @return
    */
   protected static List<String> buildColourCommands(
-          Map<Color, Map<Integer, Map<String, List<int[]>>>> colourMap)
+          Map<Color, SortedMap<Integer, Map<String, List<int[]>>>> colourMap)
   {
     /*
      * This version concatenates all commands into a single String (semi-colon
@@ -161,12 +162,12 @@ public class ChimeraCommands
    * Ordering is by order of addition (for colours and positions), natural ordering (for models and chains)
    * </pre>
    */
-  protected static Map<Color, Map<Integer, Map<String, List<int[]>>>> buildColoursMap(
+  protected static Map<Color, SortedMap<Integer, Map<String, List<int[]>>>> buildColoursMap(
           StructureSelectionManager ssm, String[] files,
           SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr,
           AlignmentI alignment)
   {
-    Map<Color, Map<Integer, Map<String, List<int[]>>>> colourMap = new LinkedHashMap<Color, Map<Integer, Map<String, List<int[]>>>>();
+    Map<Color, SortedMap<Integer, Map<String, List<int[]>>>> colourMap = new LinkedHashMap<Color, SortedMap<Integer, Map<String, List<int[]>>>>();
     Color lastColour = null;
     for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
     {
@@ -251,13 +252,13 @@ public class ChimeraCommands
    * @param chain
    */
   protected static void addColourRange(
-          Map<Color, Map<Integer, Map<String, List<int[]>>>> colourMap,
+          Map<Color, SortedMap<Integer, Map<String, List<int[]>>>> colourMap,
           Color colour, int model, int startPos, int endPos, String chain)
   {
     /*
      * Get/initialize map of data for the colour
      */
-    Map<Integer, Map<String, List<int[]>>> colourData = colourMap
+    SortedMap<Integer, Map<String, List<int[]>>> colourData = colourMap
             .get(colour);
     if (colourData == null)
     {
index 262b8a2..b05c168 100644 (file)
@@ -93,8 +93,6 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
    */
   private boolean loadingFinished = true;
 
-  public String fileLoadingError;
-
   /*
    * Map of ChimeraModel objects keyed by PDB full local file name
    */
@@ -254,18 +252,6 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   }
 
   /**
-   * Construct a title string for the viewer window based on the data Jalview
-   * knows about
-   * 
-   * @param verbose
-   * @return
-   */
-  public String getViewerTitle(boolean verbose)
-  {
-    return getViewerTitle("Chimera", verbose);
-  }
-
-  /**
    * Tells Chimera to display only the specified chains
    * 
    * @param toshow
@@ -328,6 +314,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
     releaseUIResources();
   }
 
+  @Override
   public void colourByChain()
   {
     colourBySequence = false;
@@ -343,6 +330,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
    * <li>all others - white</li>
    * </ul>
    */
+  @Override
   public void colourByCharge()
   {
     colourBySequence = false;
@@ -364,6 +352,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
    * @param _hiddenCols
    *          an array of corresponding hidden columns for each alignment
    */
+  @Override
   public void superposeStructures(AlignmentI[] _alignment,
           int[] _refStructure, ColumnSelection[] _hiddenCols)
   {
@@ -680,34 +669,15 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
           String progressMsg);
 
   /**
-   * colour any structures associated with sequences in the given alignment
-   * using the getFeatureRenderer() and getSequenceRenderer() renderers but only
-   * if colourBySequence is enabled.
+   * Sends a set of colour commands to the structure viewer
+   * 
+   * @param colourBySequenceCommands
    */
-  public void colourBySequence(boolean showFeatures,
-          jalview.api.AlignmentViewPanel alignmentv)
+  @Override
+  protected void colourBySequence(
+          StructureMappingcommandSet[] colourBySequenceCommands)
   {
-    if (!colourBySequence || !loadingFinished)
-    {
-      return;
-    }
-    if (getSsm() == null)
-    {
-      return;
-    }
-    String[] files = getPdbFile();
-
-    SequenceRenderer sr = getSequenceRenderer(alignmentv);
-
-    FeatureRenderer fr = null;
-    if (showFeatures)
-    {
-      fr = getFeatureRenderer(alignmentv);
-    }
-    AlignmentI alignment = alignmentv.getAlignment();
-
-    for (jalview.structure.StructureMappingcommandSet cpdbbyseq : getColourBySequenceCommands(
-            files, sr, fr, alignment))
+    for (StructureMappingcommandSet cpdbbyseq : colourBySequenceCommands)
     {
       for (String command : cpdbbyseq.commands)
       {
@@ -723,6 +693,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
    * @param alignment
    * @return
    */
+  @Override
   protected StructureMappingcommandSet[] getColourBySequenceCommands(
           String[] files, SequenceRenderer sr, FeatureRenderer fr,
           AlignmentI alignment)
@@ -758,40 +729,12 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   // //////////////////////////
 
   /**
-   * returns the current featureRenderer that should be used to colour the
-   * structures
-   * 
-   * @param alignment
-   * 
-   * @return
-   */
-  public abstract FeatureRenderer getFeatureRenderer(
-          AlignmentViewPanel alignment);
-
-  /**
    * instruct the Jalview binding to update the pdbentries vector if necessary
    * prior to matching the viewer's contents to the list of structure files
    * Jalview knows about.
    */
   public abstract void refreshPdbEntries();
 
-  private int getModelNum(String modelFileName)
-  {
-    String[] mfn = getPdbFile();
-    if (mfn == null)
-    {
-      return -1;
-    }
-    for (int i = 0; i < mfn.length; i++)
-    {
-      if (mfn[i].equalsIgnoreCase(modelFileName))
-      {
-        return i;
-      }
-    }
-    return -1;
-  }
-
   /**
    * map between index of model filename returned from getPdbFile and the first
    * index of models from this file in the viewer. Note - this is not trimmed -
@@ -814,17 +757,6 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   }
 
   /**
-   * returns the current sequenceRenderer that should be used to colour the
-   * structures
-   * 
-   * @param alignment
-   * 
-   * @return
-   */
-  public abstract SequenceRenderer getSequenceRenderer(
-          AlignmentViewPanel alignment);
-
-  /**
    * Construct and send a command to highlight zero, one or more atoms. We do
    * this by sending an "rlabel" command to show the residue label at that
    * position.
@@ -976,6 +908,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
     return loadNotifiesHandled;
   }
 
+  @Override
   public void setJalviewColourScheme(ColourSchemeI cs)
   {
     colourBySequence = false;
@@ -992,12 +925,14 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
 
     List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
             false);
-    for (String res : residueSet)
+    for (String resName : residueSet)
     {
-      Color col = cs.findColour(res.charAt(0));
+      char res = resName.length() == 3 ? ResidueProperties
+              .getSingleCharacterCode(resName) : resName.charAt(0);
+      Color col = cs.findColour(res, 0, null, null, 0f);
       command.append("color " + col.getRed() / normalise + ","
               + col.getGreen() / normalise + "," + col.getBlue()
-              / normalise + " ::" + res + ";");
+              / normalise + " ::" + resName + ";");
     }
 
     sendAsynchronousCommand(command.toString(), COLOURING_CHIMERA);
@@ -1048,6 +983,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
    *      .html
    * @param col
    */
+  @Override
   public void setBackgroundColour(Color col)
   {
     viewerCommandHistory(false);
index 44a2318..b5fc817 100644 (file)
@@ -59,6 +59,7 @@ import jalview.datamodel.SeqCigar;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.gui.ColourMenuHelper.ColourChangeListener;
 import jalview.gui.ViewSelectionMenu.ViewSetProvider;
 import jalview.io.AlignmentProperties;
 import jalview.io.AnnotationFile;
@@ -78,24 +79,11 @@ import jalview.io.JnetAnnotationMaker;
 import jalview.io.NewickFile;
 import jalview.io.TCoffeeScoreFile;
 import jalview.jbgui.GAlignFrame;
-import jalview.schemes.Blosum62ColourScheme;
-import jalview.schemes.BuriedColourScheme;
-import jalview.schemes.ClustalxColourScheme;
 import jalview.schemes.ColourSchemeI;
-import jalview.schemes.ColourSchemeProperty;
-import jalview.schemes.HelixColourScheme;
-import jalview.schemes.HydrophobicColourScheme;
-import jalview.schemes.NucleotideColourScheme;
-import jalview.schemes.PIDColourScheme;
-import jalview.schemes.PurinePyrimidineColourScheme;
-import jalview.schemes.RNAHelicesColourChooser;
+import jalview.schemes.ColourSchemes;
+import jalview.schemes.ResidueColourScheme;
 import jalview.schemes.ResidueProperties;
-import jalview.schemes.StrandColourScheme;
 import jalview.schemes.TCoffeeColourScheme;
-import jalview.schemes.TaylorColourScheme;
-import jalview.schemes.TurnColourScheme;
-import jalview.schemes.UserColourScheme;
-import jalview.schemes.ZappoColourScheme;
 import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
 import jalview.ws.DBRefFetcher;
@@ -126,7 +114,6 @@ import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
-import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.awt.print.PageFormat;
 import java.awt.print.PrinterJob;
@@ -149,7 +136,6 @@ import javax.swing.JInternalFrame;
 import javax.swing.JLayeredPane;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
-import javax.swing.JRadioButtonMenuItem;
 import javax.swing.JScrollPane;
 import javax.swing.SwingUtilities;
 
@@ -160,7 +146,7 @@ import javax.swing.SwingUtilities;
  * @version $Revision$
  */
 public class AlignFrame extends GAlignFrame implements DropTargetListener,
-        IProgressIndicator, AlignViewControllerGuiI
+        IProgressIndicator, AlignViewControllerGuiI, ColourChangeListener
 {
 
   public static final int DEFAULT_WIDTH = 700;
@@ -349,7 +335,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             alignPanel);
     if (viewport.getAlignmentConservationAnnotation() == null)
     {
-      BLOSUM62Colour.setEnabled(false);
+      // BLOSUM62Colour.setEnabled(false);
       conservationMenuItem.setEnabled(false);
       modifyConservation.setEnabled(false);
       // PIDColour.setEnabled(false);
@@ -369,19 +355,20 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       sortPairwiseMenuItem_actionPerformed(null);
     }
 
-    if (Desktop.desktop != null)
-    {
-      this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
-      addServiceListeners();
-      setGUINucleotide(viewport.getAlignment().isNucleotide());
-    }
-
     this.alignPanel.av
             .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
 
     setMenusFromViewport(viewport);
     buildSortByAnnotationScoresMenu();
     buildTreeMenu();
+    buildColourMenu();
+
+    if (Desktop.desktop != null)
+    {
+      this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
+      addServiceListeners();
+      setGUINucleotide();
+    }
 
     if (viewport.getWrapAlignment())
     {
@@ -848,27 +835,23 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   /**
    * Configure menu items that vary according to whether the alignment is
    * nucleotide or protein
-   * 
-   * @param nucleotide
    */
-  public void setGUINucleotide(boolean nucleotide)
+  public void setGUINucleotide()
   {
+    AlignmentI al = getViewport().getAlignment();
+    boolean nucleotide = al.isNucleotide();
+
     showTranslation.setVisible(nucleotide);
     showReverse.setVisible(nucleotide);
     showReverseComplement.setVisible(nucleotide);
     conservationMenuItem.setEnabled(!nucleotide);
-    modifyConservation.setEnabled(!nucleotide);
+    modifyConservation.setEnabled(!nucleotide
+            && conservationMenuItem.isSelected());
     showGroupConservation.setEnabled(!nucleotide);
-    rnahelicesColour.setEnabled(nucleotide);
-    nucleotideColour.setEnabled(nucleotide);
-    purinePyrimidineColour.setEnabled(nucleotide);
-    RNAInteractionColour.setEnabled(nucleotide);
+
     showComplementMenuItem.setText(nucleotide ? MessageManager
             .getString("label.protein") : MessageManager
             .getString("label.nucleotide"));
-    setColourSelected(jalview.bin.Cache.getDefault(
-            nucleotide ? Preferences.DEFAULT_COLOUR_NUC
-                    : Preferences.DEFAULT_COLOUR_PROT, "None"));
   }
 
   /**
@@ -922,8 +905,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     showSequenceLogo.setSelected(av.isShowSequenceLogo());
     normaliseSequenceLogo.setSelected(av.isNormaliseSequenceLogo());
 
-    setColourSelected(ColourSchemeProperty.getColourName(av
-            .getGlobalColourScheme()));
+    ColourMenuHelper.setColourSelected(colourMenu,
+            av.getGlobalColourScheme());
 
     showSeqFeatures.setSelected(av.isShowSequenceFeatures());
     hiddenMarkers.setState(av.getShowHiddenMarkers());
@@ -933,9 +916,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     autoCalculate.setSelected(av.autoCalculateConsensus);
     sortByTree.setSelected(av.sortByTree);
     listenToViewSelections.setSelected(av.followSelection);
-    rnahelicesColour.setEnabled(av.getAlignment().hasRNAStructure());
-    rnahelicesColour
-            .setSelected(av.getGlobalColourScheme() instanceof jalview.schemes.RNAHelicesColour);
 
     showProducts.setEnabled(canShowProducts());
     setGroovyEnabled(Desktop.getGroovyConsole() != null);
@@ -1274,8 +1254,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       FileFormatI format = fileFormat;
       cap.setText(new FormatAdapter(alignPanel, exportData.getSettings())
-              .formatSequences(format,
-                      exportData.getAlignment(),
+              .formatSequences(format, exportData.getAlignment(),
                       exportData.getOmitHidden(),
                       exportData.getStartEndPostions(),
                       viewport.getColumnSelection()));
@@ -1866,8 +1845,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
 
     String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
-            seqs,
-            omitHidden, null);
+            seqs, omitHidden, null);
 
     StringSelection ss = new StringSelection(output);
 
@@ -3292,146 +3270,19 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   }
 
   @Override
-  public void textColour_actionPerformed(ActionEvent e)
+  public void textColour_actionPerformed()
   {
     new TextColourChooser().chooseColour(alignPanel, null);
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void noColourmenuItem_actionPerformed(ActionEvent e)
-  {
-    changeColour(null);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void clustalColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new ClustalxColourScheme(viewport.getAlignment(),
-            viewport.getHiddenRepSequences()));
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void zappoColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new ZappoColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void taylorColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new TaylorColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void hydrophobicityColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new HydrophobicColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void helixColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new HelixColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void strandColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new StrandColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void turnColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new TurnColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void buriedColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new BuriedColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void nucleotideColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new NucleotideColourScheme());
-  }
-
-  @Override
-  public void purinePyrimidineColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new PurinePyrimidineColourScheme());
-  }
-
   /*
-   * public void covariationColour_actionPerformed(ActionEvent e) {
+   * public void covariationColour_actionPerformed() {
    * changeColour(new
    * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
    * ()[0])); }
    */
   @Override
-  public void annotationColour_actionPerformed(ActionEvent e)
+  public void annotationColour_actionPerformed()
   {
     new AnnotationColourChooser(viewport, alignPanel);
   }
@@ -3442,55 +3293,58 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     new AnnotationColumnChooser(viewport, alignPanel);
   }
 
+  /**
+   * Action on the user checking or unchecking the option to apply the selected
+   * colour scheme to all groups. If unchecked, groups may have their own
+   * independent colour schemes.
+   * 
+   * @param selected
+   */
   @Override
-  public void rnahelicesColour_actionPerformed(ActionEvent e)
+  public void applyToAllGroups_actionPerformed(boolean selected)
   {
-    new RNAHelicesColourChooser(viewport, alignPanel);
+    viewport.setColourAppliesToAllGroups(selected);
   }
 
   /**
-   * DOCUMENT ME!
+   * Action on user selecting a colour from the colour menu
    * 
-   * @param e
-   *          DOCUMENT ME!
+   * @param name
+   *          the name (not the menu item label!) of the colour scheme
    */
   @Override
-  protected void applyToAllGroups_actionPerformed(ActionEvent e)
+  public void changeColour_actionPerformed(String name)
   {
-    viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());
+    /*
+     * 'User Defined' opens a panel to configure or load a
+     * user-defined colour scheme
+     */
+    if (ResidueColourScheme.USER_DEFINED.equals(name))
+    {
+      new UserDefinedColours(alignPanel, null);
+      return;
+    }
+
+    /*
+     * otherwise set the chosen colour scheme (or null for 'None')
+     */
+    ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
+            viewport.getAlignment(), viewport.getHiddenRepSequences());
+    changeColour(cs);
   }
 
   /**
-   * DOCUMENT ME!
+   * Actions on setting or changing the alignment colour scheme
    * 
    * @param cs
-   *          DOCUMENT ME!
    */
   @Override
   public void changeColour(ColourSchemeI cs)
   {
     // TODO: pull up to controller method
-
     if (cs != null)
     {
-      // Make sure viewport is up to date w.r.t. any sliders
-      if (viewport.getAbovePIDThreshold())
-      {
-        int threshold = SliderPanel.setPIDSliderSource(alignPanel, cs,
-                "Background");
-        viewport.setThreshold(threshold);
-      }
-
-      if (viewport.getConservationSelected())
-      {
-        cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel,
-                cs, "Background"));
-      }
-      if (cs instanceof TCoffeeColourScheme)
-      {
-        tcoffeeColour.setEnabled(true);
-        tcoffeeColour.setSelected(true);
-      }
+      ColourMenuHelper.setColourSelected(colourMenu, cs.getSchemeName());
     }
 
     viewport.setGlobalColourScheme(cs);
@@ -3499,44 +3353,36 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   }
 
   /**
-   * DOCUMENT ME!
+   * Show the PID threshold slider panel
    */
   @Override
   protected void modifyPID_actionPerformed()
   {
-    if (viewport.getAbovePIDThreshold()
-            && viewport.getGlobalColourScheme() != null)
-    {
-      SliderPanel.setPIDSliderSource(alignPanel,
-              viewport.getGlobalColourScheme(), "Background");
-      SliderPanel.showPIDSlider();
-    }
+    SliderPanel.setPIDSliderSource(alignPanel,
+            viewport.getResidueShading(), alignPanel.getViewName());
+    SliderPanel.showPIDSlider();
   }
 
   /**
-   * DOCUMENT ME!
+   * Show the Conservation slider panel
    */
   @Override
   protected void modifyConservation_actionPerformed()
   {
-    if (viewport.getConservationSelected()
-            && viewport.getGlobalColourScheme() != null)
-    {
-      SliderPanel.setConservationSlider(alignPanel,
-              viewport.getGlobalColourScheme(), "Background");
-      SliderPanel.showConservationSlider();
-    }
+    SliderPanel.setConservationSlider(alignPanel,
+            viewport.getResidueShading(), alignPanel.getViewName());
+    SliderPanel.showConservationSlider();
   }
 
   /**
    * Action on selecting or deselecting (Colour) By Conservation
    */
   @Override
-  protected void conservationMenuItem_actionPerformed()
+  public void conservationMenuItem_actionPerformed(boolean selected)
   {
-    boolean selected = conservationMenuItem.isSelected();
     modifyConservation.setEnabled(selected);
     viewport.setConservationSelected(selected);
+    viewport.getResidueShading().setConservationApplied(selected);
 
     changeColour(viewport.getGlobalColourScheme());
     if (selected)
@@ -3553,11 +3399,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    * Action on selecting or deselecting (Colour) Above PID Threshold
    */
   @Override
-  public void abovePIDThreshold_actionPerformed()
+  public void abovePIDThreshold_actionPerformed(boolean selected)
   {
-    boolean selected = abovePIDThreshold.isSelected();
     modifyPID.setEnabled(selected);
     viewport.setAbovePIDThreshold(selected);
+    if (!selected)
+    {
+      viewport.getResidueShading().setThreshold(0,
+              viewport.isIgnoreGapsConsensus());
+    }
 
     changeColour(viewport.getGlobalColourScheme());
     if (selected)
@@ -3577,144 +3427,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    *          DOCUMENT ME!
    */
   @Override
-  public void userDefinedColour_actionPerformed(ActionEvent e)
-  {
-    if (e.getActionCommand().equals(
-            MessageManager.getString("action.user_defined")))
-    {
-      new UserDefinedColours(alignPanel, null);
-    }
-    else
-    {
-      UserColourScheme udc = (UserColourScheme) UserDefinedColours
-              .getUserColourSchemes().get(e.getActionCommand());
-
-      changeColour(udc);
-    }
-  }
-
-  public void updateUserColourMenu()
-  {
-
-    Component[] menuItems = colourMenu.getMenuComponents();
-    int iSize = menuItems.length;
-    for (int i = 0; i < iSize; i++)
-    {
-      if (menuItems[i].getName() != null
-              && menuItems[i].getName().equals("USER_DEFINED"))
-      {
-        colourMenu.remove(menuItems[i]);
-        iSize--;
-      }
-    }
-    if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
-    {
-      java.util.Enumeration userColours = jalview.gui.UserDefinedColours
-              .getUserColourSchemes().keys();
-
-      while (userColours.hasMoreElements())
-      {
-        final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(
-                userColours.nextElement().toString());
-        radioItem.setName("USER_DEFINED");
-        radioItem.addMouseListener(new MouseAdapter()
-        {
-          @Override
-          public void mousePressed(MouseEvent evt)
-          {
-            if (evt.isPopupTrigger()) // Mac
-            {
-              offerRemoval(radioItem);
-            }
-          }
-
-          @Override
-          public void mouseReleased(MouseEvent evt)
-          {
-            if (evt.isPopupTrigger()) // Windows
-            {
-              offerRemoval(radioItem);
-            }
-          }
-
-          /**
-           * @param radioItem
-           */
-          void offerRemoval(final JRadioButtonMenuItem radioItem)
-          {
-            radioItem.removeActionListener(radioItem.getActionListeners()[0]);
-
-            int option = JvOptionPane.showInternalConfirmDialog(
-                    jalview.gui.Desktop.desktop, MessageManager
-                            .getString("label.remove_from_default_list"),
-                    MessageManager
-                            .getString("label.remove_user_defined_colour"),
-                    JvOptionPane.YES_NO_OPTION);
-            if (option == JvOptionPane.YES_OPTION)
-            {
-              jalview.gui.UserDefinedColours
-                      .removeColourFromDefaults(radioItem.getText());
-              colourMenu.remove(radioItem);
-            }
-            else
-            {
-              radioItem.addActionListener(new ActionListener()
-              {
-                @Override
-                public void actionPerformed(ActionEvent evt)
-                {
-                  userDefinedColour_actionPerformed(evt);
-                }
-              });
-            }
-          }
-        });
-        radioItem.addActionListener(new ActionListener()
-        {
-          @Override
-          public void actionPerformed(ActionEvent evt)
-          {
-            userDefinedColour_actionPerformed(evt);
-          }
-        });
-
-        colourMenu.insert(radioItem, 15);
-        colours.add(radioItem);
-      }
-    }
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void PIDColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new PIDColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void BLOSUM62Colour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new Blosum62ColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
   public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
   {
     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
@@ -4342,12 +4054,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
   }
 
-  @Override
-  protected void tcoffeeColorScheme_actionPerformed(ActionEvent e)
-  {
-    changeColour(new TCoffeeColourScheme(alignPanel.getAlignment()));
-  }
-
   public TreePanel ShowNewickTree(NewickFile nf, String title)
   {
     return ShowNewickTree(nf, title, 600, 500, 4, 5);
@@ -5013,8 +4719,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           {
             if (tcf.annotateAlignment(viewport.getAlignment(), true))
             {
-              tcoffeeColour.setEnabled(true);
-              tcoffeeColour.setSelected(true);
+              buildColourMenu();
               changeColour(new TCoffeeColourScheme(viewport.getAlignment()));
               isAnnotation = true;
               statusBar
@@ -5058,8 +4763,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           }
           if (FileFormat.Jnet.equals(format))
           {
-            JPredFile predictions = new JPredFile(
-                    file, sourceType);
+            JPredFile predictions = new JPredFile(file, sourceType);
             new JnetAnnotationMaker();
             JnetAnnotationMaker.add_annotation(predictions,
                     viewport.getAlignment(), 0, false);
@@ -5129,6 +4833,28 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
 
     /*
+     * 'focus' any colour slider that is open to the selected viewport
+     */
+    if (viewport.getConservationSelected())
+    {
+      SliderPanel.setConservationSlider(alignPanel,
+              viewport.getResidueShading(), alignPanel.getViewName());
+    }
+    else
+    {
+      SliderPanel.hideConservationSlider();
+    }
+    if (viewport.getAbovePIDThreshold())
+    {
+      SliderPanel.setPIDSliderSource(alignPanel,
+              viewport.getResidueShading(), alignPanel.getViewName());
+    }
+    else
+    {
+      SliderPanel.hidePIDSlider();
+    }
+
+    /*
      * If there is a frame linked to this one in a SplitPane, switch it to the
      * same view tab index. No infinite recursion of calls should happen, since
      * tabSelectionChanged() should not get invoked on setting the selected
@@ -5828,7 +5554,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
     AlignmentI cdna = new Alignment(cdnaSeqs.toArray(new SequenceI[cdnaSeqs
             .size()]));
-    AlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
+    GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
             AlignFrame.DEFAULT_HEIGHT);
     cdna.alignAs(alignment);
     String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
@@ -5944,6 +5670,35 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             true,
             (actionEvent.getModifiers() & (ActionEvent.META_MASK | ActionEvent.CTRL_MASK)) != 0);
   }
+
+  /**
+   * Rebuilds the Colour menu, including any user-defined colours which have
+   * been loaded either on startup or during the session
+   */
+  public void buildColourMenu()
+  {
+    colourMenu.removeAll();
+
+    colourMenu.add(applyToAllGroups);
+    colourMenu.add(textColour);
+    colourMenu.addSeparator();
+
+    ColourMenuHelper.addMenuItems(colourMenu, this,
+            viewport.getAlignment(), false);
+
+    colourMenu.addSeparator();
+    colourMenu.add(conservationMenuItem);
+    colourMenu.add(modifyConservation);
+    colourMenu.add(abovePIDThreshold);
+    colourMenu.add(modifyPID);
+    colourMenu.add(annotationColour);
+
+    ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
+    String schemeName = colourScheme == null ? null : colourScheme
+            .getSchemeName();
+
+    ColourMenuHelper.setColourSelected(colourMenu, schemeName);
+  }
 }
 
 class PrintThread extends Thread
index 53d118b..69f155b 100644 (file)
@@ -41,6 +41,8 @@ import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.renderer.ResidueShader;
+import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemeProperty;
 import jalview.schemes.UserColourScheme;
 import jalview.structure.CommandListener;
@@ -61,7 +63,6 @@ import java.util.List;
 import java.util.Vector;
 
 import javax.swing.JInternalFrame;
-import javax.swing.JOptionPane;
 
 /**
  * DOCUMENT ME!
@@ -292,19 +293,20 @@ public class AlignViewport extends AlignmentViewport implements
     }
     if (propertyValue != null)
     {
-      globalColourScheme = ColourSchemeProperty.getColour(alignment,
-              propertyValue);
+      ColourSchemeI colourScheme = ColourSchemeProperty.getColourScheme(
+              alignment, propertyValue);
+      residueShading = new ResidueShader(colourScheme);
 
-      if (globalColourScheme instanceof UserColourScheme)
+      if (colourScheme instanceof UserColourScheme)
       {
-        globalColourScheme = UserDefinedColours.loadDefaultColours();
-        ((UserColourScheme) globalColourScheme).setThreshold(0,
-                isIgnoreGapsConsensus());
+        residueShading = new ResidueShader(
+                UserDefinedColours.loadDefaultColours());
+        residueShading.setThreshold(0, isIgnoreGapsConsensus());
       }
 
-      if (globalColourScheme != null)
+      if (residueShading != null)
       {
-        globalColourScheme.setConsensus(hconsensus);
+        residueShading.setConsensus(hconsensus);
       }
     }
   }
@@ -383,7 +385,11 @@ public class AlignViewport extends AlignmentViewport implements
     super.setViewStyle(settingsForView);
     setFont(new Font(viewStyle.getFontName(), viewStyle.getFontStyle(),
             viewStyle.getFontSize()), false);
-
+    if (residueShading != null)
+    {
+      residueShading.setConservationApplied(settingsForView
+              .isConservationColourSelected());
+    }
   }
 
   /**
index 39cde03..f6352d7 100644 (file)
@@ -80,9 +80,9 @@ public class AnnotationColourChooser extends AnnotationRowFilter
       oldgroupColours = new Hashtable<SequenceGroup, ColourSchemeI>();
       for (SequenceGroup sg : ap.av.getAlignment().getGroups())
       {
-        if (sg.cs != null)
+        if (sg.getColourScheme() != null)
         {
-          oldgroupColours.put(sg, sg.cs);
+          oldgroupColours.put(sg, sg.getColourScheme());
         }
       }
     }
@@ -381,7 +381,7 @@ public class AnnotationColourChooser extends AnnotationRowFilter
 
       for (SequenceGroup sg : ap.av.getAlignment().getGroups())
       {
-        sg.cs = oldgroupColours.get(sg);
+        sg.setColourScheme(oldgroupColours.get(sg));
       }
     }
   }
index c8bd69c..166e1ad 100644 (file)
@@ -366,23 +366,20 @@ public abstract class AnnotationRowFilter extends JPanel
           continue;
         }
 
+        AnnotationColourGradient scheme = null;
         if (currentColours.isSelected())
         {
-          sg.cs = new AnnotationColourGradient(currentAnn, sg.cs,
-                  selectedThresholdOption);
-          ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
-                  .isSelected());
-
+          scheme = new AnnotationColourGradient(currentAnn,
+                  sg.getColourScheme(), selectedThresholdOption);
         }
         else
         {
-          sg.cs = new AnnotationColourGradient(currentAnn,
+          scheme = new AnnotationColourGradient(currentAnn,
                   minColour.getBackground(), maxColour.getBackground(),
                   selectedThresholdOption);
-          ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
-                  .isSelected());
         }
-
+        scheme.setSeqAssociated(seqAssociated.isSelected());
+        sg.setColourScheme(scheme);
       }
     }
     return false;
index e2e54aa..ffb9639 100644 (file)
 package jalview.gui;
 
 import jalview.bin.Cache;
-import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
 import jalview.gui.StructureViewer.ViewerType;
-import jalview.io.JalviewFileChooser;
-import jalview.io.JalviewFileView;
-import jalview.schemes.BuriedColourScheme;
-import jalview.schemes.ColourSchemeI;
-import jalview.schemes.HelixColourScheme;
-import jalview.schemes.HydrophobicColourScheme;
-import jalview.schemes.PurinePyrimidineColourScheme;
-import jalview.schemes.StrandColourScheme;
-import jalview.schemes.TaylorColourScheme;
-import jalview.schemes.TurnColourScheme;
-import jalview.schemes.ZappoColourScheme;
 import jalview.structures.models.AAStructureBindingModel;
+import jalview.util.BrowserLauncher;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 import jalview.ws.dbsources.Pdb;
@@ -50,30 +38,19 @@ import java.awt.Font;
 import java.awt.Graphics;
 import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Vector;
 
 import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JColorChooser;
 import javax.swing.JInternalFrame;
 import javax.swing.JMenu;
-import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JSplitPane;
 import javax.swing.SwingUtilities;
 import javax.swing.event.InternalFrameAdapter;
 import javax.swing.event.InternalFrameEvent;
-import javax.swing.event.MenuEvent;
-import javax.swing.event.MenuListener;
 
 public class AppJmol extends StructureViewerBase
 {
@@ -92,8 +69,6 @@ public class AppJmol extends StructureViewerBase
 
   RenderPanel renderPanel;
 
-  ViewSelectionMenu seqColourBy;
-
   /**
    * 
    * @param files
@@ -137,6 +112,7 @@ public class AppJmol extends StructureViewerBase
     {
       useAlignmentPanelForSuperposition(ap);
     }
+    initMenus();
     if (leaveColouringToJmol || !usetoColour)
     {
       jmb.setColourBySequence(false);
@@ -151,7 +127,6 @@ public class AppJmol extends StructureViewerBase
       viewerColour.setSelected(false);
     }
     this.setBounds(bounds);
-    initMenus();
     setViewId(viewid);
     // jalview.gui.Desktop.addInternalFrame(this, "Loading File",
     // bounds.width,bounds.height);
@@ -165,84 +140,19 @@ public class AppJmol extends StructureViewerBase
       }
     });
     initJmol(loadStatus); // pdbentry, seq, JBPCHECK!
-
   }
 
-  private void initMenus()
+  @Override
+  protected void initMenus()
   {
-    seqColour.setSelected(jmb.isColourBySequence());
-    viewerColour.setSelected(!jmb.isColourBySequence());
-    if (_colourwith == null)
-    {
-      _colourwith = new Vector<AlignmentPanel>();
-    }
-    if (_alignwith == null)
-    {
-      _alignwith = new Vector<AlignmentPanel>();
-    }
-
-    seqColourBy = new ViewSelectionMenu(
-            MessageManager.getString("label.colour_by"), this, _colourwith,
-            new ItemListener()
-            {
-
-              @Override
-              public void itemStateChanged(ItemEvent e)
-              {
-                if (!seqColour.isSelected())
-                {
-                  seqColour.doClick();
-                }
-                else
-                {
-                  // update the jmol display now.
-                  seqColour_actionPerformed(null);
-                }
-              }
-            });
-    viewMenu.add(seqColourBy);
-    final ItemListener handler;
-    JMenu alpanels = new ViewSelectionMenu(
-            MessageManager.getString("label.superpose_with"), this,
-            _alignwith, handler = new ItemListener()
-            {
-
-              @Override
-              public void itemStateChanged(ItemEvent e)
-              {
-                alignStructs.setEnabled(_alignwith.size() > 0);
-                alignStructs.setToolTipText(MessageManager
-                        .formatMessage(
-                                "label.align_structures_using_linked_alignment_views",
-                                new String[] { new Integer(_alignwith
-                                        .size()).toString() }));
-              }
-            });
-    handler.itemStateChanged(null);
-    viewerActionMenu.add(alpanels);
-    viewerActionMenu.addMenuListener(new MenuListener()
-    {
-
-      @Override
-      public void menuSelected(MenuEvent e)
-      {
-        handler.itemStateChanged(null);
-      }
-
-      @Override
-      public void menuDeselected(MenuEvent e)
-      {
-        // TODO Auto-generated method stub
+    super.initMenus();
 
-      }
+    viewerActionMenu = new JMenu(MessageManager.getString("label.jmol"));
 
-      @Override
-      public void menuCanceled(MenuEvent e)
-      {
-        // TODO Auto-generated method stub
-
-      }
-    });
+    viewerColour
+            .setText(MessageManager.getString("label.colour_with_jmol"));
+    viewerColour.setToolTipText(MessageManager
+            .getString("label.let_jmol_manage_structure_colours"));
   }
 
   IProgressIndicator progressBar = null;
@@ -285,15 +195,6 @@ public class AppJmol extends StructureViewerBase
     openNewJmol(ap, new PDBEntry[] { pdbentry }, new SequenceI[][] { seq });
   }
 
-  /**
-   * Answers true if this viewer already involves the given PDB ID
-   */
-  @Override
-  protected boolean hasPdbId(String pdbId)
-  {
-    return jmb.hasPdbId(pdbId);
-  }
-
   private void openNewJmol(AlignmentPanel ap, PDBEntry[] pdbentrys,
           SequenceI[][] seqs)
   {
@@ -302,6 +203,7 @@ public class AppJmol extends StructureViewerBase
             pdbentrys, seqs, null);
     addAlignmentPanel(ap);
     useAlignmentPanelForColourbyseq(ap);
+
     if (pdbentrys.length > 1)
     {
       alignAddedStructures = true;
@@ -685,76 +587,6 @@ public class AppJmol extends StructureViewerBase
   }
 
   @Override
-  public void pdbFile_actionPerformed(ActionEvent actionEvent)
-  {
-    JalviewFileChooser chooser = new JalviewFileChooser(
-            jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
-
-    chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager.getString("label.save_pdb_file"));
-    chooser.setToolTipText(MessageManager.getString("action.save"));
-
-    int value = chooser.showSaveDialog(this);
-
-    if (value == JalviewFileChooser.APPROVE_OPTION)
-    {
-      BufferedReader in = null;
-      try
-      {
-        // TODO: cope with multiple PDB files in view
-        in = new BufferedReader(new FileReader(jmb.getPdbFile()[0]));
-        File outFile = chooser.getSelectedFile();
-
-        PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
-        String data;
-        while ((data = in.readLine()) != null)
-        {
-          if (!(data.indexOf("<PRE>") > -1 || data.indexOf("</PRE>") > -1))
-          {
-            out.println(data);
-          }
-        }
-        out.close();
-      } catch (Exception ex)
-      {
-        ex.printStackTrace();
-      } finally
-      {
-        if (in != null)
-        {
-          try
-          {
-            in.close();
-          } catch (IOException e)
-          {
-            // ignore
-          }
-        }
-      }
-    }
-  }
-
-  @Override
-  public void viewMapping_actionPerformed(ActionEvent actionEvent)
-  {
-    jalview.gui.CutAndPasteTransfer cap = new jalview.gui.CutAndPasteTransfer();
-    try
-    {
-      cap.appendText(jmb.printMappings());
-    } catch (OutOfMemoryError e)
-    {
-      new OOMWarning(
-              "composing sequence-structure alignments for display in text box.",
-              e);
-      cap.dispose();
-      return;
-    }
-    jalview.gui.Desktop.addInternalFrame(cap,
-            MessageManager.getString("label.pdb_sequence_mapping"), 550,
-            600);
-  }
-
-  @Override
   public void eps_actionPerformed(ActionEvent e)
   {
     makePDBImage(jalview.util.ImageMaker.TYPE.EPS);
@@ -801,135 +633,11 @@ public class AppJmol extends StructureViewerBase
   }
 
   @Override
-  public void viewerColour_actionPerformed(ActionEvent actionEvent)
-  {
-    if (viewerColour.isSelected())
-    {
-      // disable automatic sequence colouring.
-      jmb.setColourBySequence(false);
-    }
-  }
-
-  @Override
-  public void seqColour_actionPerformed(ActionEvent actionEvent)
-  {
-    jmb.setColourBySequence(seqColour.isSelected());
-    if (_colourwith == null)
-    {
-      _colourwith = new Vector<AlignmentPanel>();
-    }
-    if (jmb.isColourBySequence())
-    {
-      if (!jmb.isLoadingFromArchive())
-      {
-        if (_colourwith.size() == 0 && getAlignmentPanel() != null)
-        {
-          // Make the currently displayed alignment panel the associated view
-          _colourwith.add(getAlignmentPanel().alignFrame.alignPanel);
-        }
-      }
-      // Set the colour using the current view for the associated alignframe
-      for (AlignmentPanel ap : _colourwith)
-      {
-        jmb.colourBySequence(ap);
-      }
-    }
-  }
-
-  @Override
-  public void chainColour_actionPerformed(ActionEvent actionEvent)
-  {
-    chainColour.setSelected(true);
-    jmb.colourByChain();
-  }
-
-  @Override
-  public void chargeColour_actionPerformed(ActionEvent actionEvent)
-  {
-    chargeColour.setSelected(true);
-    jmb.colourByCharge();
-  }
-
-  @Override
-  public void zappoColour_actionPerformed(ActionEvent actionEvent)
-  {
-    zappoColour.setSelected(true);
-    jmb.setJalviewColourScheme(new ZappoColourScheme());
-  }
-
-  @Override
-  public void taylorColour_actionPerformed(ActionEvent actionEvent)
-  {
-    taylorColour.setSelected(true);
-    jmb.setJalviewColourScheme(new TaylorColourScheme());
-  }
-
-  @Override
-  public void hydroColour_actionPerformed(ActionEvent actionEvent)
-  {
-    hydroColour.setSelected(true);
-    jmb.setJalviewColourScheme(new HydrophobicColourScheme());
-  }
-
-  @Override
-  public void helixColour_actionPerformed(ActionEvent actionEvent)
-  {
-    helixColour.setSelected(true);
-    jmb.setJalviewColourScheme(new HelixColourScheme());
-  }
-
-  @Override
-  public void strandColour_actionPerformed(ActionEvent actionEvent)
-  {
-    strandColour.setSelected(true);
-    jmb.setJalviewColourScheme(new StrandColourScheme());
-  }
-
-  @Override
-  public void turnColour_actionPerformed(ActionEvent actionEvent)
-  {
-    turnColour.setSelected(true);
-    jmb.setJalviewColourScheme(new TurnColourScheme());
-  }
-
-  @Override
-  public void buriedColour_actionPerformed(ActionEvent actionEvent)
-  {
-    buriedColour.setSelected(true);
-    jmb.setJalviewColourScheme(new BuriedColourScheme());
-  }
-
-  @Override
-  public void purinePyrimidineColour_actionPerformed(ActionEvent actionEvent)
-  {
-    setJalviewColourScheme(new PurinePyrimidineColourScheme());
-  }
-
-  @Override
-  public void userColour_actionPerformed(ActionEvent actionEvent)
-  {
-    userColour.setSelected(true);
-    new UserDefinedColours(this, null);
-  }
-
-  @Override
-  public void backGround_actionPerformed(ActionEvent actionEvent)
-  {
-    java.awt.Color col = JColorChooser
-            .showDialog(this, MessageManager
-                    .getString("label.select_backgroud_colour"), null);
-    if (col != null)
-    {
-      jmb.setBackgroundColour(col);
-    }
-  }
-
-  @Override
   public void showHelp_actionPerformed(ActionEvent actionEvent)
   {
     try
     {
-      jalview.util.BrowserLauncher
+      BrowserLauncher
               .openURL("http://jmol.sourceforge.net/docs/JmolUserGuide/");
     } catch (Exception ex)
     {
@@ -978,7 +686,7 @@ public class AppJmol extends StructureViewerBase
     {
       getSize(currentSize);
 
-      if (jmb != null && jmb.fileLoadingError != null)
+      if (jmb != null && jmb.hasFileLoadingError())
       {
         g.setColor(Color.black);
         g.fillRect(0, 0, currentSize.width, currentSize.height);
@@ -1021,104 +729,6 @@ public class AppJmol extends StructureViewerBase
     }
   }
 
-  public void updateTitleAndMenus()
-  {
-    if (jmb.fileLoadingError != null && jmb.fileLoadingError.length() > 0)
-    {
-      repaint();
-      return;
-    }
-    setChainMenuItems(jmb.getChainNames());
-
-    this.setTitle(jmb.getViewerTitle());
-    if (jmb.getPdbFile().length > 1 && jmb.getSequence().length > 1)
-    {
-      viewerActionMenu.setVisible(true);
-    }
-    if (!jmb.isLoadingFromArchive())
-    {
-      seqColour_actionPerformed(null);
-    }
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * jalview.jbgui.GStructureViewer#alignStructs_actionPerformed(java.awt.event
-   * .ActionEvent)
-   */
-  @Override
-  protected void alignStructs_actionPerformed(ActionEvent actionEvent)
-  {
-    alignStructs_withAllAlignPanels();
-  }
-
-  private void alignStructs_withAllAlignPanels()
-  {
-    if (getAlignmentPanel() == null)
-    {
-      return;
-    }
-    ;
-    if (_alignwith.size() == 0)
-    {
-      _alignwith.add(getAlignmentPanel());
-    }
-    ;
-    try
-    {
-      AlignmentI[] als = new Alignment[_alignwith.size()];
-      ColumnSelection[] alc = new ColumnSelection[_alignwith.size()];
-      int[] alm = new int[_alignwith.size()];
-      int a = 0;
-
-      for (AlignmentPanel ap : _alignwith)
-      {
-        als[a] = ap.av.getAlignment();
-        alm[a] = -1;
-        alc[a++] = ap.av.getColumnSelection();
-      }
-      jmb.superposeStructures(als, alm, alc);
-    } catch (Exception e)
-    {
-      StringBuffer sp = new StringBuffer();
-      for (AlignmentPanel ap : _alignwith)
-      {
-        sp.append("'" + ap.alignFrame.getTitle() + "' ");
-      }
-      Cache.log.info("Couldn't align structures with the " + sp.toString()
-              + "associated alignment panels.", e);
-
-    }
-
-  }
-
-  @Override
-  public void setJalviewColourScheme(ColourSchemeI ucs)
-  {
-    jmb.setJalviewColourScheme(ucs);
-
-  }
-
-  /**
-   * 
-   * @param alignment
-   * @return first alignment panel displaying given alignment, or the default
-   *         alignment panel
-   */
-  public AlignmentPanel getAlignmentPanelFor(AlignmentI alignment)
-  {
-    for (AlignmentPanel ap : getAllAlignmentPanels())
-    {
-      if (ap.av.getAlignment() == alignment)
-      {
-        return ap;
-      }
-    }
-    return getAlignmentPanel();
-  }
-
   @Override
   public AAStructureBindingModel getBinding()
   {
@@ -1138,9 +748,8 @@ public class AppJmol extends StructureViewerBase
   }
 
   @Override
-  protected AAStructureBindingModel getBindingModel()
+  protected String getViewerName()
   {
-    return jmb;
+    return "Jmol";
   }
-
 }
index b82eef3..530f4fe 100644 (file)
 package jalview.gui;
 
 import jalview.bin.Cache;
-import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
 import jalview.ext.rbvi.chimera.JalviewChimeraBinding;
 import jalview.gui.StructureViewer.ViewerType;
 import jalview.io.DataSourceType;
-import jalview.io.JalviewFileChooser;
-import jalview.io.JalviewFileView;
 import jalview.io.StructureFile;
-import jalview.schemes.BuriedColourScheme;
-import jalview.schemes.ColourSchemeI;
-import jalview.schemes.HelixColourScheme;
-import jalview.schemes.HydrophobicColourScheme;
-import jalview.schemes.PurinePyrimidineColourScheme;
-import jalview.schemes.StrandColourScheme;
-import jalview.schemes.TaylorColourScheme;
-import jalview.schemes.TurnColourScheme;
-import jalview.schemes.ZappoColourScheme;
 import jalview.structures.models.AAStructureBindingModel;
+import jalview.util.BrowserLauncher;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 import jalview.ws.dbsources.Pdb;
 
 import java.awt.event.ActionEvent;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
-import java.util.Vector;
 
 import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JColorChooser;
 import javax.swing.JInternalFrame;
-import javax.swing.JMenu;
-import javax.swing.JOptionPane;
 import javax.swing.event.InternalFrameAdapter;
 import javax.swing.event.InternalFrameEvent;
-import javax.swing.event.MenuEvent;
-import javax.swing.event.MenuListener;
 
 /**
  * GUI elements for handling an external chimera display
@@ -98,88 +74,21 @@ public class ChimeraViewFrame extends StructureViewerBase
   /**
    * Initialise menu options.
    */
-  private void initMenus()
+  @Override
+  protected void initMenus()
   {
+    super.initMenus();
+
     viewerActionMenu.setText(MessageManager.getString("label.chimera"));
+
     viewerColour.setText(MessageManager
             .getString("label.colour_with_chimera"));
     viewerColour.setToolTipText(MessageManager
             .getString("label.let_chimera_manage_structure_colours"));
-    helpItem.setText(MessageManager.getString("label.chimera_help"));
-    seqColour.setSelected(jmb.isColourBySequence());
-    viewerColour.setSelected(!jmb.isColourBySequence());
-    if (_colourwith == null)
-    {
-      _colourwith = new Vector<AlignmentPanel>();
-    }
-    if (_alignwith == null)
-    {
-      _alignwith = new Vector<AlignmentPanel>();
-    }
-
-    // save As not yet implemented
-    savemenu.setVisible(false);
 
-    ViewSelectionMenu seqColourBy = new ViewSelectionMenu(
-            MessageManager.getString("label.colour_by"), this, _colourwith,
-            new ItemListener()
-            {
-              @Override
-              public void itemStateChanged(ItemEvent e)
-              {
-                if (!seqColour.isSelected())
-                {
-                  seqColour.doClick();
-                }
-                else
-                {
-                  // update the Chimera display now.
-                  seqColour_actionPerformed(null);
-                }
-              }
-            });
-    viewMenu.add(seqColourBy);
+    helpItem.setText(MessageManager.getString("label.chimera_help"));
+    savemenu.setVisible(false); // not yet implemented
     viewMenu.add(fitToWindow);
-
-    final ItemListener handler;
-    JMenu alpanels = new ViewSelectionMenu(
-            MessageManager.getString("label.superpose_with"), this,
-            _alignwith, handler = new ItemListener()
-            {
-              @Override
-              public void itemStateChanged(ItemEvent e)
-              {
-                alignStructs.setEnabled(_alignwith.size() > 0);
-                alignStructs.setToolTipText(MessageManager
-                        .formatMessage(
-                                "label.align_structures_using_linked_alignment_views",
-                                new Object[] { new Integer(_alignwith
-                                        .size()).toString() }));
-              }
-            });
-    handler.itemStateChanged(null);
-    viewerActionMenu.add(alpanels);
-    viewerActionMenu.addMenuListener(new MenuListener()
-    {
-
-      @Override
-      public void menuSelected(MenuEvent e)
-      {
-        handler.itemStateChanged(null);
-      }
-
-      @Override
-      public void menuDeselected(MenuEvent e)
-      {
-        // TODO Auto-generated method stub
-      }
-
-      @Override
-      public void menuCanceled(MenuEvent e)
-      {
-        // TODO Auto-generated method stub
-      }
-    });
   }
 
   /**
@@ -233,15 +142,6 @@ public class ChimeraViewFrame extends StructureViewerBase
     }
   }
 
-  /**
-   * Answers true if this viewer already involves the given PDB ID
-   */
-  @Override
-  protected boolean hasPdbId(String pdbId)
-  {
-    return jmb.hasPdbId(pdbId);
-  }
-
   private void openNewChimera(AlignmentPanel ap, PDBEntry[] pdbentrys,
           SequenceI[][] seqs)
   {
@@ -251,6 +151,7 @@ public class ChimeraViewFrame extends StructureViewerBase
             ap.getStructureSelectionManager(), pdbentrys, seqs, null);
     addAlignmentPanel(ap);
     useAlignmentPanelForColourbyseq(ap);
+
     if (pdbentrys.length > 1)
     {
       alignAddedStructures = true;
@@ -275,8 +176,6 @@ public class ChimeraViewFrame extends StructureViewerBase
 
   }
 
-
-
   /**
    * Create a new viewer from saved session state data including Chimera session
    * file
@@ -372,7 +271,7 @@ public class ChimeraViewFrame extends StructureViewerBase
   {
     jmb.setFinishedInit(false);
     jalview.gui.Desktop.addInternalFrame(this,
-            jmb.getViewerTitle("Chimera", true), getBounds().width,
+            jmb.getViewerTitle(getViewerName(), true), getBounds().width,
             getBounds().height);
 
     if (!jmb.launchChimera())
@@ -439,7 +338,8 @@ public class ChimeraViewFrame extends StructureViewerBase
       {
         String prompt = MessageManager.formatMessage(
                 "label.confirm_close_chimera",
-                new Object[] { jmb.getViewerTitle("Chimera", false) });
+                        new Object[] { jmb.getViewerTitle(getViewerName(),
+                                false) });
         prompt = JvSwingUtils.wrapTooltip(true, prompt);
         int confirm = JvOptionPane.showConfirmDialog(this, prompt,
                 MessageManager.getString("label.close_viewer"),
@@ -569,7 +469,7 @@ public class ChimeraViewFrame extends StructureViewerBase
           try
           {
             int pos = filePDBpos.get(num).intValue();
-            long startTime = startProgressBar("Chimera "
+            long startTime = startProgressBar(getViewerName() + " "
                     + MessageManager.getString("status.opening_file_for")
                     + " " + pe.getId());
             jmb.openFile(pe);
@@ -734,76 +634,6 @@ public class ChimeraViewFrame extends StructureViewerBase
   }
 
   @Override
-  public void pdbFile_actionPerformed(ActionEvent actionEvent)
-  {
-    JalviewFileChooser chooser = new JalviewFileChooser(
-            jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
-
-    chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager.getString("label.save_pdb_file"));
-    chooser.setToolTipText(MessageManager.getString("action.save"));
-
-    int value = chooser.showSaveDialog(this);
-
-    if (value == JalviewFileChooser.APPROVE_OPTION)
-    {
-      BufferedReader in = null;
-      try
-      {
-        // TODO: cope with multiple PDB files in view
-        in = new BufferedReader(new FileReader(jmb.getPdbFile()[0]));
-        File outFile = chooser.getSelectedFile();
-
-        PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
-        String data;
-        while ((data = in.readLine()) != null)
-        {
-          if (!(data.indexOf("<PRE>") > -1 || data.indexOf("</PRE>") > -1))
-          {
-            out.println(data);
-          }
-        }
-        out.close();
-      } catch (Exception ex)
-      {
-        ex.printStackTrace();
-      } finally
-      {
-        if (in != null)
-        {
-          try
-          {
-            in.close();
-          } catch (IOException e)
-          {
-            e.printStackTrace();
-          }
-        }
-      }
-    }
-  }
-
-  @Override
-  public void viewMapping_actionPerformed(ActionEvent actionEvent)
-  {
-    jalview.gui.CutAndPasteTransfer cap = new jalview.gui.CutAndPasteTransfer();
-    try
-    {
-      cap.appendText(jmb.printMappings());
-    } catch (OutOfMemoryError e)
-    {
-      new OOMWarning(
-              "composing sequence-structure alignments for display in text box.",
-              e);
-      cap.dispose();
-      return;
-    }
-    jalview.gui.Desktop.addInternalFrame(cap,
-            MessageManager.getString("label.pdb_sequence_mapping"), 550,
-            600);
-  }
-
-  @Override
   public void eps_actionPerformed(ActionEvent e)
   {
     throw new Error(
@@ -820,237 +650,17 @@ public class ChimeraViewFrame extends StructureViewerBase
   }
 
   @Override
-  public void viewerColour_actionPerformed(ActionEvent actionEvent)
-  {
-    if (viewerColour.isSelected())
-    {
-      // disable automatic sequence colouring.
-      jmb.setColourBySequence(false);
-    }
-  }
-
-  @Override
-  public void seqColour_actionPerformed(ActionEvent actionEvent)
-  {
-    jmb.setColourBySequence(seqColour.isSelected());
-    if (_colourwith == null)
-    {
-      _colourwith = new Vector<AlignmentPanel>();
-    }
-    if (jmb.isColourBySequence())
-    {
-      if (!jmb.isLoadingFromArchive())
-      {
-        if (_colourwith.size() == 0 && getAlignmentPanel() != null)
-        {
-          // Make the currently displayed alignment panel the associated view
-          _colourwith.add(getAlignmentPanel().alignFrame.alignPanel);
-        }
-      }
-      // Set the colour using the current view for the associated alignframe
-      for (AlignmentPanel ap : _colourwith)
-      {
-        jmb.colourBySequence(ap.av.isShowSequenceFeatures(), ap);
-      }
-    }
-  }
-
-  @Override
-  public void chainColour_actionPerformed(ActionEvent actionEvent)
-  {
-    chainColour.setSelected(true);
-    jmb.colourByChain();
-  }
-
-  @Override
-  public void chargeColour_actionPerformed(ActionEvent actionEvent)
-  {
-    chargeColour.setSelected(true);
-    jmb.colourByCharge();
-  }
-
-  @Override
-  public void zappoColour_actionPerformed(ActionEvent actionEvent)
-  {
-    zappoColour.setSelected(true);
-    jmb.setJalviewColourScheme(new ZappoColourScheme());
-  }
-
-  @Override
-  public void taylorColour_actionPerformed(ActionEvent actionEvent)
-  {
-    taylorColour.setSelected(true);
-    jmb.setJalviewColourScheme(new TaylorColourScheme());
-  }
-
-  @Override
-  public void hydroColour_actionPerformed(ActionEvent actionEvent)
-  {
-    hydroColour.setSelected(true);
-    jmb.setJalviewColourScheme(new HydrophobicColourScheme());
-  }
-
-  @Override
-  public void helixColour_actionPerformed(ActionEvent actionEvent)
-  {
-    helixColour.setSelected(true);
-    jmb.setJalviewColourScheme(new HelixColourScheme());
-  }
-
-  @Override
-  public void strandColour_actionPerformed(ActionEvent actionEvent)
-  {
-    strandColour.setSelected(true);
-    jmb.setJalviewColourScheme(new StrandColourScheme());
-  }
-
-  @Override
-  public void turnColour_actionPerformed(ActionEvent actionEvent)
-  {
-    turnColour.setSelected(true);
-    jmb.setJalviewColourScheme(new TurnColourScheme());
-  }
-
-  @Override
-  public void buriedColour_actionPerformed(ActionEvent actionEvent)
-  {
-    buriedColour.setSelected(true);
-    jmb.setJalviewColourScheme(new BuriedColourScheme());
-  }
-
-  @Override
-  public void purinePyrimidineColour_actionPerformed(ActionEvent actionEvent)
-  {
-    setJalviewColourScheme(new PurinePyrimidineColourScheme());
-  }
-
-  @Override
-  public void userColour_actionPerformed(ActionEvent actionEvent)
-  {
-    userColour.setSelected(true);
-    new UserDefinedColours(this, null);
-  }
-
-  @Override
-  public void backGround_actionPerformed(ActionEvent actionEvent)
-  {
-    java.awt.Color col = JColorChooser
-            .showDialog(this, MessageManager
-                    .getString("label.select_backgroud_colour"), null);
-    if (col != null)
-    {
-      jmb.setBackgroundColour(col);
-    }
-  }
-
-  @Override
   public void showHelp_actionPerformed(ActionEvent actionEvent)
   {
     try
     {
-      jalview.util.BrowserLauncher
+      BrowserLauncher
               .openURL("https://www.cgl.ucsf.edu/chimera/docs/UsersGuide");
     } catch (Exception ex)
     {
     }
   }
 
-  public void updateTitleAndMenus()
-  {
-    if (jmb.fileLoadingError != null && jmb.fileLoadingError.length() > 0)
-    {
-      repaint();
-      return;
-    }
-    setChainMenuItems(jmb.getChainNames());
-
-    this.setTitle(jmb.getViewerTitle("Chimera", true));
-    if (jmb.getPdbFile().length > 1 && jmb.getSequence().length > 1)
-    {
-      viewerActionMenu.setVisible(true);
-    }
-    if (!jmb.isLoadingFromArchive())
-    {
-      seqColour_actionPerformed(null);
-    }
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * jalview.jbgui.GStructureViewer#alignStructs_actionPerformed(java.awt.event
-   * .ActionEvent)
-   */
-  @Override
-  protected void alignStructs_actionPerformed(ActionEvent actionEvent)
-  {
-    alignStructs_withAllAlignPanels();
-  }
-
-  private void alignStructs_withAllAlignPanels()
-  {
-    if (getAlignmentPanel() == null)
-    {
-      return;
-    }
-
-    if (_alignwith.size() == 0)
-    {
-      _alignwith.add(getAlignmentPanel());
-    }
-
-    try
-    {
-      AlignmentI[] als = new Alignment[_alignwith.size()];
-      ColumnSelection[] alc = new ColumnSelection[_alignwith.size()];
-      int[] alm = new int[_alignwith.size()];
-      int a = 0;
-
-      for (AlignmentPanel ap : _alignwith)
-      {
-        als[a] = ap.av.getAlignment();
-        alm[a] = -1;
-        alc[a++] = ap.av.getColumnSelection();
-      }
-      jmb.superposeStructures(als, alm, alc);
-    } catch (Exception e)
-    {
-      StringBuffer sp = new StringBuffer();
-      for (AlignmentPanel ap : _alignwith)
-      {
-        sp.append("'" + ap.alignFrame.getTitle() + "' ");
-      }
-      Cache.log.info("Couldn't align structures with the " + sp.toString()
-              + "associated alignment panels.", e);
-    }
-  }
-
-  @Override
-  public void setJalviewColourScheme(ColourSchemeI ucs)
-  {
-    jmb.setJalviewColourScheme(ucs);
-
-  }
-
-  /**
-   * 
-   * @param alignment
-   * @return first alignment panel displaying given alignment, or the default
-   *         alignment panel
-   */
-  public AlignmentPanel getAlignmentPanelFor(AlignmentI alignment)
-  {
-    for (AlignmentPanel ap : getAllAlignmentPanels())
-    {
-      if (ap.av.getAlignment() == alignment)
-      {
-        return ap;
-      }
-    }
-    return getAlignmentPanel();
-  }
-
   @Override
   public AAStructureBindingModel getBinding()
   {
@@ -1140,8 +750,8 @@ public class ChimeraViewFrame extends StructureViewerBase
   }
 
   @Override
-  protected AAStructureBindingModel getBindingModel()
+  protected String getViewerName()
   {
-    return jmb;
+    return "Chimera";
   }
 }
diff --git a/src/jalview/gui/ColourMenuHelper.java b/src/jalview/gui/ColourMenuHelper.java
new file mode 100644 (file)
index 0000000..31780d6
--- /dev/null
@@ -0,0 +1,286 @@
+package jalview.gui;
+
+import jalview.bin.Cache;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ColourSchemes;
+import jalview.schemes.ResidueColourScheme;
+import jalview.schemes.UserColourScheme;
+import jalview.util.MessageManager;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JMenu;
+import javax.swing.JRadioButtonMenuItem;
+
+public class ColourMenuHelper
+{
+  public interface ColourChangeListener
+  {
+    void changeColour_actionPerformed(String name);
+  }
+
+  /**
+   * Adds items to the colour menu, as mutually exclusive members of a button
+   * group. The callback handler is responsible for the action on selecting any
+   * of these options. The callback method receives the name of the selected
+   * colour, or "None" or "User Defined". This method returns the ButtonGroup to
+   * which items were added.
+   * <ul>
+   * <li>None</li>
+   * <li>Clustal</li>
+   * <li>...other 'built-in' colours</li>
+   * <li>...any user-defined colours</li>
+   * <li>User Defined..</li>
+   * </ul>
+   * 
+   * @param colourMenu
+   *          the menu to attach items to
+   * @param client
+   *          a callback to handle menu selection
+   * @param coll
+   *          the data the menu is being built for
+   * @param simpleOnly
+   *          if true, only simple per-residue colour schemes are included
+   */
+  public static ButtonGroup addMenuItems(final JMenu colourMenu,
+          final ColourChangeListener client, AnnotatedCollectionI coll,
+          boolean simpleOnly)
+  {
+    /*
+     * ButtonGroup groups those items whose 
+     * selection is mutually exclusive
+     */
+    ButtonGroup colours = new ButtonGroup();
+
+    if (!simpleOnly)
+    {
+      JRadioButtonMenuItem noColourmenuItem = new JRadioButtonMenuItem(
+              MessageManager.getString("label.none"));
+      noColourmenuItem.setName(ResidueColourScheme.NONE);
+      noColourmenuItem.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          client.changeColour_actionPerformed(ResidueColourScheme.NONE);
+        }
+      });
+      colourMenu.add(noColourmenuItem);
+      colours.add(noColourmenuItem);
+    }
+
+    /*
+     * scan registered colour schemes (built-in or user-defined
+     * and add them to the menu (in the order they were registered)
+     */
+    Iterable<ColourSchemeI> colourSchemes = ColourSchemes.getInstance()
+            .getColourSchemes();
+    for (ColourSchemeI scheme : colourSchemes)
+    {
+      if (simpleOnly && !scheme.isSimple())
+      {
+        continue;
+      }
+
+      /*
+       * button text is i18n'd but the name is the canonical name of
+       * the colour scheme (inspected in setColourSelected())
+       */
+      final String name = scheme.getSchemeName();
+      String label = MessageManager.getStringOrReturn("label.colourScheme_"
+              + name.toLowerCase().replace(" ", "_"), name);
+      final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(label);
+      radioItem.setName(name);
+      radioItem.setEnabled(scheme.isApplicableTo(coll));
+      if (scheme instanceof UserColourScheme)
+      {
+        /*
+         * user-defined colour scheme loaded on startup or during the
+         * Jalview session; right-click on this offers the option to
+         * remove it as a colour choice
+         */
+        radioItem.addMouseListener(new MouseAdapter()
+        {
+          @Override
+          public void mousePressed(MouseEvent evt)
+          {
+            if (evt.isPopupTrigger()) // Mac
+            {
+              offerRemoval();
+            }
+          }
+
+          @Override
+          public void mouseReleased(MouseEvent evt)
+          {
+            if (evt.isPopupTrigger()) // Windows
+            {
+              offerRemoval();
+            }
+          }
+
+          void offerRemoval()
+          {
+            ActionListener al = radioItem.getActionListeners()[0];
+            radioItem.removeActionListener(al);
+            int option = JvOptionPane.showInternalConfirmDialog(
+                    Desktop.desktop, MessageManager
+                            .getString("label.remove_from_default_list"),
+                    MessageManager
+                            .getString("label.remove_user_defined_colour"),
+                    JvOptionPane.YES_NO_OPTION);
+            if (option == JvOptionPane.YES_OPTION)
+            {
+              ColourSchemes.getInstance().removeColourScheme(
+                      radioItem.getName());
+              colourMenu.remove(radioItem);
+              updatePreferences();
+            }
+            else
+            {
+              radioItem.addActionListener(al);
+            }
+          }
+        });
+      }
+      radioItem.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent evt)
+        {
+          client.changeColour_actionPerformed(name);
+        }
+      });
+      colourMenu.add(radioItem);
+      colours.add(radioItem);
+    }
+
+    /*
+     * only add the option to load/configure a user-defined colour
+     * to the AlignFrame colour menu
+     */
+    if (client instanceof AlignFrame)
+    {
+      final String label = MessageManager.getString("action.user_defined");
+      JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem(
+              label);
+      userDefinedColour.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          client.changeColour_actionPerformed(ResidueColourScheme.USER_DEFINED);
+        }
+      });
+      colourMenu.add(userDefinedColour);
+      colours.add(userDefinedColour);
+    }
+
+    return colours;
+  }
+
+  /**
+   * Marks as selected the colour menu item matching the given name, or the
+   * first item ('None') if no match is found
+   * 
+   * @param colourMenu
+   * @param colourName
+   */
+  public static void setColourSelected(JMenu colourMenu, String colourName)
+  {
+    if (colourName == null)
+    {
+      return;
+    }
+
+    JRadioButtonMenuItem none = null;
+
+    /*
+     * select the radio button whose name matches the colour name
+     * (not the button text, as it may be internationalised)
+     */
+    for (Component menuItem : colourMenu.getMenuComponents())
+    {
+      if (menuItem instanceof JRadioButtonMenuItem)
+      {
+        String buttonName = ((JRadioButtonMenuItem) menuItem).getName();
+        if (colourName.equals(buttonName))
+        {
+          ((JRadioButtonMenuItem) menuItem).setSelected(true);
+          return;
+        }
+        if (ResidueColourScheme.NONE.equals(buttonName))
+        {
+          none = (JRadioButtonMenuItem) menuItem;
+        }
+      }
+    }
+    if (none != null)
+    {
+      none.setSelected(true);
+    }
+  }
+
+  /**
+   * Marks as selected the colour menu item matching the given colour scheme, or
+   * the first item ('None') if no match is found
+   * 
+   * @param colourMenu
+   * @param cs
+   */
+  public static void setColourSelected(JMenu colourMenu, ColourSchemeI cs)
+  {
+    setColourSelected(colourMenu, cs == null ? ResidueColourScheme.NONE
+            : cs.getSchemeName());
+  }
+
+  /**
+   * Updates the USER_DEFINE_COLOURS preference to remove any de-registered
+   * colour scheme
+   */
+  static void updatePreferences()
+  {
+    StringBuilder coloursFound = new StringBuilder();
+    String[] files = Cache.getProperty("USER_DEFINED_COLOURS").split("\\|");
+
+    /*
+     * the property does not include the scheme name, it is in the file;
+     * so just load the colour schemes and discard any whose name is not
+     * registered
+     */
+    for (String file : files)
+    {
+      try
+      {
+        UserColourScheme ucs = ColourSchemes.loadColourScheme(file);
+        if (ucs != null
+                && ColourSchemes.getInstance().nameExists(ucs.getName()))
+        {
+          if (coloursFound.length() > 0)
+          {
+            coloursFound.append("|");
+          }
+          coloursFound.append(file);
+        }
+      } catch (Exception ex)
+      {
+        System.out.println("Error loading User ColourFile\n" + ex);
+      }
+    }
+
+    if (coloursFound.toString().length() > 1)
+    {
+      Cache.setProperty("USER_DEFINED_COLOURS", coloursFound.toString());
+    }
+    else
+    {
+      Cache.applicationProperties.remove("USER_DEFINED_COLOURS");
+    }
+  }
+}
index ae911ed..ed6a3c5 100644 (file)
@@ -26,7 +26,7 @@ import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.schemes.FeatureColour;
-import jalview.schemes.UserColourScheme;
+import jalview.util.ColorUtils;
 import jalview.util.MessageManager;
 
 import java.awt.BorderLayout;
@@ -211,7 +211,7 @@ public class FeatureRenderer extends
           FeatureColourI col = getFeatureStyle(name.getText());
           if (col == null)
           {
-            col = new FeatureColour(UserColourScheme
+            col = new FeatureColour(ColorUtils
                     .createColourFromName(name.getText()));
           }
           oldcol = fcol = col;
index 12b46e4..3ac453f 100644 (file)
@@ -39,6 +39,7 @@ import jalview.ext.varna.RnaModel;
 import jalview.gui.StructureViewer.ViewerType;
 import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
+import jalview.renderer.ResidueShaderI;
 import jalview.schemabinding.version2.AlcodMap;
 import jalview.schemabinding.version2.AlcodonFrame;
 import jalview.schemabinding.version2.Annotation;
@@ -1174,38 +1175,43 @@ public class Jalview2XML
           // group has references so set its ID field
           jGroup.setId(groupRefs.get(sg));
         }
-        if (sg.cs != null)
+        ColourSchemeI colourScheme = sg.getColourScheme();
+        if (colourScheme != null)
         {
-          if (sg.cs.conservationApplied())
+          ResidueShaderI groupColourScheme = sg
+                  .getGroupColourScheme();
+          if (groupColourScheme.conservationApplied())
           {
-            jGroup.setConsThreshold(sg.cs.getConservationInc());
+            jGroup.setConsThreshold(groupColourScheme.getConservationInc());
 
-            if (sg.cs instanceof jalview.schemes.UserColourScheme)
+            if (colourScheme instanceof jalview.schemes.UserColourScheme)
             {
-              jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
+              jGroup.setColour(setUserColourScheme(colourScheme,
+                      userColours, jms));
             }
             else
             {
-              jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
+              jGroup.setColour(colourScheme.getSchemeName());
             }
           }
-          else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
+          else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
           {
             jGroup.setColour("AnnotationColourGradient");
             jGroup.setAnnotationColours(constructAnnotationColours(
-                    (jalview.schemes.AnnotationColourGradient) sg.cs,
+                    (jalview.schemes.AnnotationColourGradient) colourScheme,
                     userColours, jms));
           }
-          else if (sg.cs instanceof jalview.schemes.UserColourScheme)
+          else if (colourScheme instanceof jalview.schemes.UserColourScheme)
           {
-            jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
+            jGroup.setColour(setUserColourScheme(colourScheme,
+                    userColours, jms));
           }
           else
           {
-            jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
+            jGroup.setColour(colourScheme.getSchemeName());
           }
 
-          jGroup.setPidThreshold(sg.cs.getThreshold());
+          jGroup.setPidThreshold(groupColourScheme.getThreshold());
         }
 
         jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
@@ -1288,23 +1294,20 @@ public class Jalview2XML
                 .getGlobalColourScheme()));
       }
 
+      ResidueShaderI vcs = av.getResidueShading();
       ColourSchemeI cs = av.getGlobalColourScheme();
 
       if (cs != null)
       {
-        if (cs.conservationApplied())
+        if (vcs.conservationApplied())
         {
-          view.setConsThreshold(cs.getConservationInc());
+          view.setConsThreshold(vcs.getConservationInc());
           if (cs instanceof jalview.schemes.UserColourScheme)
           {
             view.setBgColour(setUserColourScheme(cs, userColours, jms));
           }
         }
-
-        if (cs instanceof ResidueColourScheme)
-        {
-          view.setPidThreshold(cs.getThreshold());
-        }
+        view.setPidThreshold(vcs.getThreshold());
       }
 
       view.setConservationSelected(av.getConservationSelected());
@@ -1723,8 +1726,7 @@ public class Jalview2XML
     }
     else
     {
-      ac.setColourScheme(ColourSchemeProperty.getColourName(acg
-              .getBaseColour()));
+      ac.setColourScheme(ColourSchemeProperty.getColourName(acg.getBaseColour()));
     }
 
     ac.setMaxColour(acg.getMaxColour().getRGB());
@@ -3341,19 +3343,13 @@ public class Jalview2XML
                   && jGroup.getAnnotationColours() != null)
           {
             addAnnotSchemeGroup = true;
-            cs = null;
           }
           else
           {
-            cs = ColourSchemeProperty.getColour(al, jGroup.getColour());
-          }
-
-          if (cs != null)
-          {
-            cs.setThreshold(jGroup.getPidThreshold(), true);
-            cs.setConservationInc(jGroup.getConsThreshold());
+            cs = ColourSchemeProperty.getColourScheme(al, jGroup.getColour());
           }
         }
+        int pidThreshold = jGroup.getPidThreshold();
 
         Vector<SequenceI> seqs = new Vector<SequenceI>();
 
@@ -3376,7 +3372,8 @@ public class Jalview2XML
         SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
                 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
                 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
-
+        sg.getGroupColourScheme().setThreshold(pidThreshold, true);
+        sg.getGroupColourScheme().setConservationInc(jGroup.getConsThreshold());
         sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
 
         sg.textColour = new java.awt.Color(jGroup.getTextCol1());
@@ -3442,8 +3439,8 @@ public class Jalview2XML
         if (addAnnotSchemeGroup)
         {
           // reconstruct the annotation colourscheme
-          sg.cs = constructAnnotationColour(jGroup.getAnnotationColours(),
-                  null, al, jms, false);
+          sg.setColourScheme(constructAnnotationColour(
+                  jGroup.getAnnotationColours(), null, al, jms, false));
         }
       }
     }
@@ -4472,21 +4469,21 @@ public class Jalview2XML
       }
       else
       {
-        cs = ColourSchemeProperty.getColour(al, view.getBgColour());
-      }
-
-      if (cs != null)
-      {
-        cs.setConsensus(af.viewport.getSequenceConsensusHash());
+        cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
       }
     }
 
     af.viewport.setGlobalColourScheme(cs);
+    af.viewport.getResidueShading().setThreshold(
+            view.getPidThreshold(), true);
+    af.viewport.getResidueShading().setConsensus(
+            af.viewport.getSequenceConsensusHash());
     af.viewport.setColourAppliesToAllGroups(false);
 
     if (view.getConservationSelected() && cs != null)
     {
-      cs.setConservationInc(view.getConsThreshold());
+      af.viewport.getResidueShading().setConservationInc(
+              view.getConsThreshold());
     }
 
     af.changeColour(cs);
@@ -4707,7 +4704,7 @@ public class Jalview2XML
       propagateAnnColour = true;
       for (jalview.datamodel.SequenceGroup sg : al.getGroups())
       {
-        if (sg.cs instanceof AnnotationColourGradient)
+        if (sg.getColourScheme() instanceof AnnotationColourGradient)
         {
           propagateAnnColour = false;
         }
@@ -4731,7 +4728,8 @@ public class Jalview2XML
                     );
           }
 
-          if (viewAnnColour.getColourScheme().equals("None"))
+          if (viewAnnColour.getColourScheme().equals(
+                  ResidueColourScheme.NONE))
           {
             cs = new AnnotationColourGradient(
                     annAlignment.getAlignmentAnnotation()[i],
@@ -4751,7 +4749,7 @@ public class Jalview2XML
           {
             cs = new AnnotationColourGradient(
                     annAlignment.getAlignmentAnnotation()[i],
-                    ColourSchemeProperty.getColour(al,
+                    ColourSchemeProperty.getColourScheme(al,
                             viewAnnColour.getColourScheme()),
                     viewAnnColour.getAboveThreshold());
           }
@@ -4779,7 +4777,7 @@ public class Jalview2XML
               }
 
               /*
-               * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
+               * if (viewAnnColour.getColourScheme().equals(ResidueColourScheme.NONE)) { sg.cs =
                * new AnnotationColourGradient(
                * annAlignment.getAlignmentAnnotation()[i], new
                * java.awt.Color(viewAnnColour. getMinColour()), new
@@ -4787,9 +4785,10 @@ public class Jalview2XML
                * viewAnnColour.getAboveThreshold()); } else
                */
               {
-                sg.cs = new AnnotationColourGradient(
-                        annAlignment.getAlignmentAnnotation()[i], sg.cs,
-                        viewAnnColour.getAboveThreshold());
+                sg.setColourScheme(new AnnotationColourGradient(
+                        annAlignment.getAlignmentAnnotation()[i], sg
+                                .getColourScheme(), viewAnnColour
+                                .getAboveThreshold()));
                 if (cs instanceof AnnotationColourGradient)
                 {
                   if (viewAnnColour.hasPerSequence())
index 52f61b1..e751a2c 100755 (executable)
@@ -52,8 +52,6 @@ import java.util.Vector;
 import java.util.jar.JarEntry;
 import java.util.jar.JarInputStream;
 
-import javax.swing.JOptionPane;
-
 /**
  * DOCUMENT ME!
  * 
@@ -333,15 +331,10 @@ public class Jalview2XML_V1
           }
           else
           {
-            cs = ColourSchemeProperty.getColour(al, groups[i].getColour());
-          }
-
-          if (cs != null)
-          {
-            cs.setThreshold(groups[i].getPidThreshold(), true);
+            cs = ColourSchemeProperty.getColourScheme(al, groups[i].getColour());
           }
-
         }
+        int pidThreshold = groups[i].getPidThreshold();
 
         Vector seqs = new Vector();
         int[] ids = groups[i].getSeq();
@@ -355,6 +348,7 @@ public class Jalview2XML_V1
                 seqs, groups[i].getName(), cs, groups[i].getDisplayBoxes(),
                 groups[i].getDisplayText(), groups[i].getColourText(),
                 groups[i].getStart(), groups[i].getEnd());
+        sg.getGroupColourScheme().setThreshold(pidThreshold, true);
 
         sg.setOutlineColour(new java.awt.Color(groups[i].getOutlineColour()));
 
@@ -401,23 +395,27 @@ public class Jalview2XML_V1
       }
       else
       {
-        cs = ColourSchemeProperty.getColour(al, view.getBgColour());
+        cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
       }
 
-      if (cs != null)
-      {
-        cs.setThreshold(view.getPidThreshold(), true);
-        cs.setConsensus(af.viewport.getSequenceConsensusHash());
-      }
+      // if (cs != null)
+      // {
+      // cs.setThreshold(view.getPidThreshold(), true);
+      // cs.setConsensus(af.viewport.getSequenceConsensusHash());
+      // }
     }
 
-    af.viewport.setGlobalColourScheme(cs);
+    af.viewport.getResidueShading().setThreshold(
+            view.getPidThreshold(), true);
+    af.viewport.getResidueShading().setConsensus(
+            af.viewport.getSequenceConsensusHash());
     af.viewport.setColourAppliesToAllGroups(false);
     af.alignPanel.updateLayout();
     af.changeColour(cs);
     if (view.getConservationSelected() && cs != null)
     {
-      cs.setConservationInc(view.getConsThreshold());
+      af.viewport.getResidueShading().setConservationInc(
+              view.getConsThreshold());
     }
 
     af.viewport.setColourAppliesToAllGroups(true);
index 801b285..a797872 100644 (file)
@@ -95,7 +95,7 @@ public class JalviewChimeraBindingModel extends JalviewChimeraBinding
     }
     if (!isLoadingFromArchive())
     {
-      colourBySequence(ap.av.isShowSequenceFeatures(), ap);
+      colourBySequence(ap);
     }
   }
 
index aa01bf5..58ed008 100644 (file)
@@ -193,7 +193,7 @@ public class PCAPanel extends GPCAPanel implements Runnable,
   public void bgcolour_actionPerformed(ActionEvent e)
   {
     Color col = JColorChooser.showDialog(this,
-            MessageManager.getString("label.select_backgroud_colour"),
+            MessageManager.getString("label.select_background_colour"),
             rc.bgColour);
 
     if (col != null)
index 6a68334..81c3d4f 100644 (file)
@@ -38,24 +38,17 @@ import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.gui.ColourMenuHelper.ColourChangeListener;
 import jalview.io.FileFormatI;
 import jalview.io.FileFormats;
 import jalview.io.FormatAdapter;
 import jalview.io.SequenceAnnotationReport;
 import jalview.schemes.AnnotationColourGradient;
 import jalview.schemes.Blosum62ColourScheme;
-import jalview.schemes.BuriedColourScheme;
-import jalview.schemes.ClustalxColourScheme;
-import jalview.schemes.HelixColourScheme;
-import jalview.schemes.HydrophobicColourScheme;
-import jalview.schemes.NucleotideColourScheme;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ColourSchemes;
 import jalview.schemes.PIDColourScheme;
-import jalview.schemes.PurinePyrimidineColourScheme;
-import jalview.schemes.StrandColourScheme;
-import jalview.schemes.TaylorColourScheme;
-import jalview.schemes.TurnColourScheme;
-import jalview.schemes.UserColourScheme;
-import jalview.schemes.ZappoColourScheme;
+import jalview.schemes.ResidueColourScheme;
 import jalview.util.GroupUrlLink;
 import jalview.util.GroupUrlLink.UrlStringTooLongException;
 import jalview.util.MessageManager;
@@ -71,16 +64,15 @@ import java.util.Hashtable;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.SortedMap;
 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.JPopupMenu;
-import javax.swing.JRadioButtonMenuItem;
 
 /**
  * DOCUMENT ME!
@@ -88,40 +80,12 @@ import javax.swing.JRadioButtonMenuItem;
  * @author $author$
  * @version $Revision: 1.118 $
  */
-public class PopupMenu extends JPopupMenu
+public class PopupMenu extends JPopupMenu implements ColourChangeListener
 {
   JMenu groupMenu = new JMenu();
 
   JMenuItem groupName = new JMenuItem();
 
-  protected JRadioButtonMenuItem clustalColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem zappoColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem taylorColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem hydrophobicityColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem helixColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem strandColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem turnColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem buriedColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem PIDColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem BLOSUM62Colour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem purinePyrimidineColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem RNAInteractionColour = new JRadioButtonMenuItem();
-
-  JRadioButtonMenuItem noColourmenuItem = new JRadioButtonMenuItem();
-
   protected JCheckBoxMenuItem abovePIDColour = new JCheckBoxMenuItem();
 
   protected JMenuItem modifyPID = new JMenuItem();
@@ -152,8 +116,6 @@ public class PopupMenu extends JPopupMenu
 
   JMenuItem outline = new JMenuItem();
 
-  JRadioButtonMenuItem nucleotideMenuItem = new JRadioButtonMenuItem();
-
   JMenu colourMenu = new JMenu();
 
   JCheckBoxMenuItem showBoxes = new JCheckBoxMenuItem();
@@ -242,22 +204,6 @@ public class PopupMenu extends JPopupMenu
     this.ap = ap;
     sequence = seq;
 
-    ButtonGroup colours = new ButtonGroup();
-    colours.add(noColourmenuItem);
-    colours.add(clustalColour);
-    colours.add(zappoColour);
-    colours.add(taylorColour);
-    colours.add(hydrophobicityColour);
-    colours.add(helixColour);
-    colours.add(strandColour);
-    colours.add(turnColour);
-    colours.add(buriedColour);
-    colours.add(userDefinedColour);
-    colours.add(PIDColour);
-    colours.add(BLOSUM62Colour);
-    colours.add(purinePyrimidineColour);
-    colours.add(RNAInteractionColour);
-
     for (String ff : FileFormats.getInstance().getWritableFormats(true))
     {
       JMenuItem item = new JMenuItem(ff);
@@ -468,7 +414,6 @@ public class PopupMenu extends JPopupMenu
 
         add(menuItem);
       }
-
     }
 
     SequenceGroup sg = ap.av.getSelectionGroup();
@@ -480,63 +425,9 @@ public class PopupMenu extends JPopupMenu
       groupName.setText(MessageManager
               .getString("label.edit_name_and_description_current_group"));
 
-      if (sg.cs instanceof ZappoColourScheme)
-      {
-        zappoColour.setSelected(true);
-      }
-      else if (sg.cs instanceof TaylorColourScheme)
-      {
-        taylorColour.setSelected(true);
-      }
-      else if (sg.cs instanceof PIDColourScheme)
-      {
-        PIDColour.setSelected(true);
-      }
-      else if (sg.cs instanceof Blosum62ColourScheme)
-      {
-        BLOSUM62Colour.setSelected(true);
-      }
-      else if (sg.cs instanceof UserColourScheme)
-      {
-        userDefinedColour.setSelected(true);
-      }
-      else if (sg.cs instanceof HydrophobicColourScheme)
-      {
-        hydrophobicityColour.setSelected(true);
-      }
-      else if (sg.cs instanceof HelixColourScheme)
-      {
-        helixColour.setSelected(true);
-      }
-      else if (sg.cs instanceof StrandColourScheme)
-      {
-        strandColour.setSelected(true);
-      }
-      else if (sg.cs instanceof TurnColourScheme)
-      {
-        turnColour.setSelected(true);
-      }
-      else if (sg.cs instanceof BuriedColourScheme)
-      {
-        buriedColour.setSelected(true);
-      }
-      else if (sg.cs instanceof ClustalxColourScheme)
-      {
-        clustalColour.setSelected(true);
-      }
-      else if (sg.cs instanceof PurinePyrimidineColourScheme)
-      {
-        purinePyrimidineColour.setSelected(true);
-      }
+      ColourMenuHelper.setColourSelected(colourMenu, sg.getColourScheme());
 
-      /*
-       * else if (sg.cs instanceof CovariationColourScheme) {
-       * covariationColour.setSelected(true); }
-       */
-      else
-      {
-        noColourmenuItem.setSelected(true);
-      }
+      conservationMenuItem.setEnabled(!sg.isNucleotide());
 
       if (sg.cs != null)
       {
@@ -1097,7 +988,7 @@ public class PopupMenu extends JPopupMenu
         sequenceSelectionDetails_actionPerformed();
       }
     });
-    PIDColour.setFocusPainted(false);
+
     unGroupMenuItem
             .setText(MessageManager.getString("action.remove_group"));
     unGroupMenuItem.addActionListener(new ActionListener()
@@ -1128,17 +1019,6 @@ public class PopupMenu extends JPopupMenu
         outline_actionPerformed();
       }
     });
-    nucleotideMenuItem
-            .setText(MessageManager.getString("label.nucleotide"));
-    nucleotideMenuItem.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        nucleotideMenuItem_actionPerformed();
-      }
-    });
-    colourMenu.setText(MessageManager.getString("label.group_colour"));
     showBoxes.setText(MessageManager.getString("action.boxes"));
     showBoxes.setState(true);
     showBoxes.addActionListener(new ActionListener()
@@ -1169,7 +1049,7 @@ public class PopupMenu extends JPopupMenu
       }
     });
     displayNonconserved.setText(MessageManager
-            .getString("label.show_non_conversed"));
+            .getString("label.show_non_conserved"));
     displayNonconserved.setState(true);
     displayNonconserved.addActionListener(new ActionListener()
     {
@@ -1245,15 +1125,6 @@ public class PopupMenu extends JPopupMenu
         sequenceFeature_actionPerformed();
       }
     });
-    textColour.setText(MessageManager.getString("label.text_colour"));
-    textColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        textColour_actionPerformed();
-      }
-    });
     jMenu1.setText(MessageManager.getString("label.group"));
     pdbStructureDialog.setText(MessageManager
             .getString("label.show_pdbstruct_dialog"));
@@ -1345,51 +1216,10 @@ public class PopupMenu extends JPopupMenu
     sequenceMenu.add(sequenceName);
     sequenceMenu.add(sequenceDetails);
     sequenceMenu.add(makeReferenceSeq);
-    colourMenu.add(textColour);
-    colourMenu.add(noColourmenuItem);
-    colourMenu.add(clustalColour);
-    colourMenu.add(BLOSUM62Colour);
-    colourMenu.add(PIDColour);
-    colourMenu.add(zappoColour);
-    colourMenu.add(taylorColour);
-    colourMenu.add(hydrophobicityColour);
-    colourMenu.add(helixColour);
-    colourMenu.add(strandColour);
-    colourMenu.add(turnColour);
-    colourMenu.add(buriedColour);
-    colourMenu.add(nucleotideMenuItem);
-    if (ap.getAlignment().isNucleotide())
-    {
-      // JBPNote - commented since the colourscheme isn't functional
-      colourMenu.add(purinePyrimidineColour);
-    }
-    colourMenu.add(userDefinedColour);
 
-    if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
-    {
-      java.util.Enumeration userColours = jalview.gui.UserDefinedColours
-              .getUserColourSchemes().keys();
+    initColourMenu();
+    buildColourMenu();
 
-      while (userColours.hasMoreElements())
-      {
-        JMenuItem item = new JMenuItem(userColours.nextElement().toString());
-        item.addActionListener(new ActionListener()
-        {
-          @Override
-          public void actionPerformed(ActionEvent evt)
-          {
-            userDefinedColour_actionPerformed(evt);
-          }
-        });
-        colourMenu.add(item);
-      }
-    }
-
-    colourMenu.addSeparator();
-    colourMenu.add(conservationMenuItem);
-    colourMenu.add(modifyConservation);
-    colourMenu.add(abovePIDColour);
-    colourMenu.add(modifyPID);
     editMenu.add(copy);
     editMenu.add(cut);
     editMenu.add(editSequence);
@@ -1407,144 +1237,32 @@ public class PopupMenu extends JPopupMenu
     jMenu1.add(showColourText);
     jMenu1.add(outline);
     jMenu1.add(displayNonconserved);
-    noColourmenuItem.setText(MessageManager.getString("label.none"));
-    noColourmenuItem.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        noColourmenuItem_actionPerformed();
-      }
-    });
-
-    clustalColour.setText(MessageManager
-            .getString("label.clustalx_colours"));
-    clustalColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        clustalColour_actionPerformed();
-      }
-    });
-    zappoColour.setText(MessageManager.getString("label.zappo"));
-    zappoColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        zappoColour_actionPerformed();
-      }
-    });
-    taylorColour.setText(MessageManager.getString("label.taylor"));
-    taylorColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        taylorColour_actionPerformed();
-      }
-    });
-    hydrophobicityColour.setText(MessageManager
-            .getString("label.hydrophobicity"));
-    hydrophobicityColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        hydrophobicityColour_actionPerformed();
-      }
-    });
-    helixColour.setText(MessageManager.getString("label.helix_propensity"));
-    helixColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        helixColour_actionPerformed();
-      }
-    });
-    strandColour.setText(MessageManager
-            .getString("label.strand_propensity"));
-    strandColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        strandColour_actionPerformed();
-      }
-    });
-    turnColour.setText(MessageManager.getString("label.turn_propensity"));
-    turnColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        turnColour_actionPerformed();
-      }
-    });
-    buriedColour.setText(MessageManager.getString("label.buried_index"));
-    buriedColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        buriedColour_actionPerformed();
-      }
-    });
-    userDefinedColour.setText(MessageManager
-            .getString("action.user_defined"));
-    userDefinedColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        userDefinedColour_actionPerformed(e);
-      }
-    });
-    PIDColour
-            .setText(MessageManager.getString("label.percentage_identity"));
-    PIDColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        PIDColour_actionPerformed();
-      }
-    });
-    BLOSUM62Colour.setText(MessageManager.getString("label.blosum62"));
-    BLOSUM62Colour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        BLOSUM62Colour_actionPerformed();
-      }
-    });
-    purinePyrimidineColour.setText(MessageManager
-            .getString("label.purine_pyrimidine"));
-    purinePyrimidineColour.addActionListener(new ActionListener()
+  }
+  
+  /**
+   * Constructs the entries for the colour menu
+   */
+  protected void initColourMenu()
+  {
+    colourMenu.setText(MessageManager.getString("label.group_colour"));
+    textColour.setText(MessageManager.getString("label.text_colour"));
+    textColour.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        purinePyrimidineColour_actionPerformed();
+        textColour_actionPerformed();
       }
     });
 
-    /*
-     * covariationColour.addActionListener(new ActionListener() {
-     * public void actionPerformed(ActionEvent e) {
-     * covariationColour_actionPerformed(); } });
-     */
     abovePIDColour.setText(MessageManager
-            .getString("label.above_identity_percentage"));
+            .getString("label.above_identity_threshold"));
     abovePIDColour.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        abovePIDColour_actionPerformed();
+        abovePIDColour_actionPerformed(abovePIDColour.isSelected());
       }
     });
 
@@ -1560,13 +1278,14 @@ public class PopupMenu extends JPopupMenu
     });
 
     conservationMenuItem.setText(MessageManager
-            .getString("label.conservation"));
+            .getString("action.by_conservation"));
     conservationMenuItem.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        conservationMenuItem_actionPerformed();
+        conservationMenuItem_actionPerformed(conservationMenuItem
+                .isSelected());
       }
     });
 
@@ -1582,6 +1301,33 @@ public class PopupMenu extends JPopupMenu
     });
   }
 
+  /**
+   * Builds the group colour sub-menu, including any user-defined colours which
+   * were loaded at startup or during the Jalview session
+   */
+  protected void buildColourMenu()
+  {
+    SequenceGroup sg = ap.av.getSelectionGroup();
+    if (sg == null)
+    {
+      /*
+       * popup menu with no sequence group scope
+       */
+      return;
+    }
+    colourMenu.removeAll();
+    colourMenu.add(textColour);
+    colourMenu.addSeparator();
+
+    ColourMenuHelper.addMenuItems(colourMenu, this, sg, false);
+
+    colourMenu.addSeparator();
+    colourMenu.add(conservationMenuItem);
+    colourMenu.add(modifyConservation);
+    colourMenu.add(abovePIDColour);
+    colourMenu.add(modifyPID);
+  }
+
   protected void modifyConservation_actionPerformed()
   {
     SequenceGroup sg = getGroup();
@@ -1628,7 +1374,7 @@ public class PopupMenu extends JPopupMenu
      * Temporary store to hold distinct calcId / type pairs for the tooltip.
      * Using TreeMap means calcIds are shown in alphabetical order.
      */
-    Map<String, String> tipEntries = new TreeMap<String, String>();
+    SortedMap<String, String> tipEntries = new TreeMap<String, String>();
     final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<SequenceI, List<AlignmentAnnotation>>();
     AlignmentI al = this.ap.av.getAlignment();
     AlignmentUtils.findAddableReferenceAnnotations(forSequences,
@@ -1777,121 +1523,6 @@ public class PopupMenu extends JPopupMenu
     PaintRefresher.Refresh(this, ap.av.getSequenceSetId());
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void clustalColour_actionPerformed()
-  {
-    SequenceGroup sg = getGroup();
-    sg.cs = new ClustalxColourScheme(sg, ap.av.getHiddenRepSequences());
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void zappoColour_actionPerformed()
-  {
-    getGroup().cs = new ZappoColourScheme();
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void taylorColour_actionPerformed()
-  {
-    getGroup().cs = new TaylorColourScheme();
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void hydrophobicityColour_actionPerformed()
-  {
-    getGroup().cs = new HydrophobicColourScheme();
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void helixColour_actionPerformed()
-  {
-    getGroup().cs = new HelixColourScheme();
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void strandColour_actionPerformed()
-  {
-    getGroup().cs = new StrandColourScheme();
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void turnColour_actionPerformed()
-  {
-    getGroup().cs = new TurnColourScheme();
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void buriedColour_actionPerformed()
-  {
-    getGroup().cs = new BuriedColourScheme();
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  public void nucleotideMenuItem_actionPerformed()
-  {
-    getGroup().cs = new NucleotideColourScheme();
-    refresh();
-  }
-
-  protected void purinePyrimidineColour_actionPerformed()
-  {
-    getGroup().cs = new PurinePyrimidineColourScheme();
-    refresh();
-  }
-
   /*
    * protected void covariationColour_actionPerformed() { getGroup().cs = new
    * CovariationColourScheme(sequence.getAnnotation()[0]); refresh(); }
@@ -1899,10 +1530,12 @@ public class PopupMenu extends JPopupMenu
   /**
    * DOCUMENT ME!
    * 
+   * @param selected
+   * 
    * @param e
    *          DOCUMENT ME!
    */
-  protected void abovePIDColour_actionPerformed()
+  public void abovePIDColour_actionPerformed(boolean selected)
   {
     SequenceGroup sg = getGroup();
     if (sg.cs == null)
@@ -1910,14 +1543,14 @@ public class PopupMenu extends JPopupMenu
       return;
     }
 
-    boolean selected = abovePIDColour.isSelected();
     if (selected)
     {
       sg.cs.setConsensus(AAFrequency.calculate(
               sg.getSequences(ap.av.getHiddenRepSequences()),
               sg.getStartRes(), sg.getEndRes() + 1));
 
-      int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
+      int threshold = SliderPanel.setPIDSliderSource(ap,
+              sg.getGroupColourScheme(), getGroup()
               .getName());
 
       sg.cs.setThreshold(threshold, ap.av.isIgnoreGapsConsensus());
@@ -1936,30 +1569,6 @@ public class PopupMenu extends JPopupMenu
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void userDefinedColour_actionPerformed(ActionEvent e)
-  {
-    SequenceGroup sg = getGroup();
-
-    if (e.getSource().equals(userDefinedColour))
-    {
-      new UserDefinedColours(ap, sg);
-    }
-    else
-    {
-      UserColourScheme udc = (UserColourScheme) UserDefinedColours
-              .getUserColourSchemes().get(e.getActionCommand());
-
-      sg.cs = udc;
-    }
-    refresh();
-  }
-
-  /**
    * Open a panel where the user can choose which types of sequence annotation
    * to show or hide.
    * 
@@ -1977,54 +1586,7 @@ public class PopupMenu extends JPopupMenu
    * @param e
    *          DOCUMENT ME!
    */
-  protected void PIDColour_actionPerformed()
-  {
-    SequenceGroup sg = getGroup();
-    sg.cs = new PIDColourScheme();
-    sg.cs.setConsensus(AAFrequency.calculate(
-            sg.getSequences(ap.av.getHiddenRepSequences()),
-            sg.getStartRes(), sg.getEndRes() + 1));
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void BLOSUM62Colour_actionPerformed()
-  {
-    SequenceGroup sg = getGroup();
-
-    sg.cs = new Blosum62ColourScheme();
-
-    sg.cs.setConsensus(AAFrequency.calculate(
-            sg.getSequences(ap.av.getHiddenRepSequences()),
-            sg.getStartRes(), sg.getEndRes() + 1));
-
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void noColourmenuItem_actionPerformed()
-  {
-    getGroup().cs = null;
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void conservationMenuItem_actionPerformed()
+  public void conservationMenuItem_actionPerformed(boolean selected)
   {
     SequenceGroup sg = getGroup();
     if (sg.cs == null)
@@ -2032,7 +1594,6 @@ public class PopupMenu extends JPopupMenu
       return;
     }
 
-    boolean selected = conservationMenuItem.isSelected();
     if (selected)
     {
       // JBPNote: Conservation name shouldn't be i18n translated
@@ -2042,10 +1603,10 @@ public class PopupMenu extends JPopupMenu
 
       c.calculate();
       c.verdict(false, ap.av.getConsPercGaps());
-
       sg.cs.setConservation(c);
 
-      SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
+      SliderPanel.setConservationSlider(ap, sg.getGroupColourScheme(),
+              sg.getName());
       SliderPanel.showConservationSlider();
     }
     else
@@ -2072,7 +1633,7 @@ public class PopupMenu extends JPopupMenu
             AnnotationColourGradient.NO_THRESHOLD);
 
     acg.setPredefinedColours(true);
-    sg.cs = acg;
+    sg.setColourScheme(acg);
 
     refresh();
   }
@@ -2332,8 +1893,7 @@ public class PopupMenu extends JPopupMenu
     // or we simply trust the user wants
     // wysiwig behaviour
 
-    FileFormatI fileFormat = FileFormats.getInstance().forName(
-            e.getActionCommand());
+    FileFormatI fileFormat = FileFormats.getInstance().forName(e.getActionCommand());
     cap.setText(new FormatAdapter(ap).formatSequences(fileFormat, ap, true));
   }
 
@@ -2438,4 +1998,41 @@ public class PopupMenu extends JPopupMenu
     }
   }
 
+  /**
+   * Action on user selecting an item from the colour menu (that does not have
+   * its bespoke action handler)
+   * 
+   * @return
+   */
+  @Override
+  public void changeColour_actionPerformed(String colourSchemeName)
+  {
+    SequenceGroup sg = getGroup();
+    if (ResidueColourScheme.USER_DEFINED.equals(colourSchemeName))
+    {
+      /*
+       * open a panel to load or configure a user-defined colour scheme
+       */
+      new UserDefinedColours(ap, sg);
+    }
+    else
+    {
+      /*
+       * switch to the chosen colour scheme (or null for None)
+       */
+      ColourSchemeI colourScheme = ColourSchemes.getInstance().getColourScheme(
+              colourSchemeName, sg, ap.av.getHiddenRepSequences());
+      sg.setColourScheme(colourScheme);
+      if (colourScheme instanceof Blosum62ColourScheme
+              || colourScheme instanceof PIDColourScheme)
+      {
+        sg.cs.setConsensus(AAFrequency.calculate(
+                sg.getSequences(ap.av.getHiddenRepSequences()),
+                sg.getStartRes(), sg.getEndRes() + 1));
+      }
+    }
+
+    refresh();
+  }
+
 }
index 422745a..d32ff46 100755 (executable)
@@ -34,7 +34,9 @@ import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
 import jalview.jbgui.GPreferences;
 import jalview.jbgui.GSequenceLink;
-import jalview.schemes.ColourSchemeProperty;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ColourSchemes;
+import jalview.schemes.ResidueColourScheme;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 import jalview.ws.sifts.SiftsSettings;
@@ -290,12 +292,16 @@ public class Preferences extends GPreferences
     /*
      * Set Colours tab defaults
      */
-    for (int i = ColourSchemeProperty.FIRST_COLOUR; i <= ColourSchemeProperty.LAST_COLOUR; i++)
+    protColour.addItem(ResidueColourScheme.NONE);
+    nucColour.addItem(ResidueColourScheme.NONE);
+    for (ColourSchemeI cs : ColourSchemes.getInstance().getColourSchemes())
     {
-      protColour.addItem(ColourSchemeProperty.getColourName(i));
-      nucColour.addItem(ColourSchemeProperty.getColourName(i));
+      String name = cs.getSchemeName();
+      protColour.addItem(name);
+      nucColour.addItem(name);
     }
-    String oldProp = Cache.getDefault(DEFAULT_COLOUR, "None");
+    String oldProp = Cache.getDefault(DEFAULT_COLOUR,
+            ResidueColourScheme.NONE);
     String newProp = Cache.getDefault(DEFAULT_COLOUR_PROT, null);
     protColour.setSelectedItem(newProp != null ? newProp : oldProp);
     newProp = Cache.getDefault(DEFAULT_COLOUR_NUC, null);
index 4fdb25a..e402d28 100644 (file)
@@ -35,6 +35,7 @@ import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.io.SequenceAnnotationReport;
+import jalview.renderer.ResidueShaderI;
 import jalview.schemes.ResidueProperties;
 import jalview.structure.SelectionListener;
 import jalview.structure.SelectionSource;
@@ -1654,14 +1655,14 @@ public class SeqPanel extends JPanel implements MouseListener,
 
       if (av.getConservationSelected())
       {
-        SliderPanel.setConservationSlider(ap, av.getGlobalColourScheme(),
-                "Background");
+        SliderPanel.setConservationSlider(ap, av.getResidueShading(),
+                ap.getViewName());
       }
 
       if (av.getAbovePIDThreshold())
       {
-        SliderPanel.setPIDSliderSource(ap, av.getGlobalColourScheme(),
-                "Background");
+        SliderPanel.setPIDSliderSource(ap, av.getResidueShading(),
+                ap.getViewName());
       }
       if ((stretchGroup != null) && (stretchGroup.getEndRes() == res))
       {
@@ -1732,15 +1733,15 @@ public class SeqPanel extends JPanel implements MouseListener,
       stretchGroup.cs.alignmentChanged(stretchGroup,
               av.getHiddenRepSequences());
 
+      ResidueShaderI groupColourScheme = stretchGroup.getGroupColourScheme();
+      String name = stretchGroup.getName();
       if (stretchGroup.cs.conservationApplied())
       {
-        SliderPanel.setConservationSlider(ap, stretchGroup.cs,
-                stretchGroup.getName());
+        SliderPanel.setConservationSlider(ap, groupColourScheme, name);
       }
       if (stretchGroup.cs.getThreshold() > 0)
       {
-        SliderPanel.setPIDSliderSource(ap, stretchGroup.cs,
-                stretchGroup.getName());
+        SliderPanel.setPIDSliderSource(ap, groupColourScheme, name);
       }
     }
     PaintRefresher.Refresh(this, av.getSequenceSetId());
index 64fe053..95c3261 100755 (executable)
@@ -23,7 +23,8 @@ package jalview.gui;
 import jalview.api.FeatureRenderer;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
-import jalview.schemes.ColourSchemeI;
+import jalview.renderer.ResidueShaderI;
+import jalview.util.Comparison;
 
 import java.awt.Color;
 import java.awt.FontMetrics;
@@ -92,12 +93,12 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
     {
       if (currentSequenceGroup.getDisplayBoxes())
       {
-        getBoxColour(currentSequenceGroup.cs, seq, i);
+        getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq, i);
       }
     }
     else if (av.getShowBoxes())
     {
-      getBoxColour(av.getGlobalColourScheme(), seq, i);
+      getBoxColour(av.getResidueShading(), seq, i);
     }
 
     return resBoxColour;
@@ -131,21 +132,21 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
   /**
    * DOCUMENT ME!
    * 
-   * @param cs
+   * @param shader
    *          DOCUMENT ME!
    * @param seq
    *          DOCUMENT ME!
    * @param i
    *          DOCUMENT ME!
    */
-  void getBoxColour(ColourSchemeI cs, SequenceI seq, int i)
+  void getBoxColour(ResidueShaderI shader, SequenceI seq, int i)
   {
-    if (cs != null)
+    if (shader != null)
     {
-      resBoxColour = cs.findColour(seq.getCharAt(i), i, seq);
+      resBoxColour = shader.findColour(seq.getCharAt(i),
+              i, seq);
     }
-    else if (forOverview
-            && !jalview.util.Comparison.isGap(seq.getCharAt(i)))
+    else if (forOverview && !Comparison.isGap(seq.getCharAt(i)))
     {
       resBoxColour = Color.lightGray;
     }
@@ -234,14 +235,14 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
         {
           if (currentSequenceGroup.getDisplayBoxes())
           {
-            getBoxColour(currentSequenceGroup.cs, seq, i);
+            getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq,
+                    i);
           }
         }
         else if (av.getShowBoxes())
         {
-          getBoxColour(av.getGlobalColourScheme(), seq, i);
+          getBoxColour(av.getResidueShading(), seq, i);
         }
-
       }
 
       if (resBoxColour != tempColour)
@@ -345,7 +346,8 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
                   || currentSequenceGroup.getColourText())
           {
             getboxColour = true;
-            getBoxColour(currentSequenceGroup.cs, seq, i);
+            getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq,
+                    i);
 
             if (currentSequenceGroup.getColourText())
             {
@@ -385,7 +387,7 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
           if (av.getColourText())
           {
             getboxColour = true;
-            getBoxColour(av.getGlobalColourScheme(), seq, i);
+            getBoxColour(av.getResidueShading(), seq, i);
 
             if (av.getShowBoxes())
             {
@@ -401,7 +403,7 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
           {
             if (!getboxColour)
             {
-              getBoxColour(av.getGlobalColourScheme(), seq, i);
+              getBoxColour(av.getResidueShading(), seq, i);
             }
 
             if (resBoxColour.getRed() + resBoxColour.getBlue()
index 62ee954..0c4e03e 100755 (executable)
@@ -22,13 +22,12 @@ package jalview.gui;
 
 import jalview.datamodel.SequenceGroup;
 import jalview.jbgui.GSliderPanel;
-import jalview.schemes.ColourSchemeI;
+import jalview.renderer.ResidueShaderI;
 import jalview.util.MessageManager;
 
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.beans.PropertyVetoException;
-import java.util.Iterator;
 
 import javax.swing.JInternalFrame;
 import javax.swing.JLayeredPane;
@@ -45,6 +44,8 @@ import javax.swing.event.InternalFrameEvent;
  */
 public class SliderPanel extends GSliderPanel
 {
+  private static final String BACKGROUND = "Background";
+
   static JInternalFrame conservationSlider;
 
   static JInternalFrame PIDSlider;
@@ -53,7 +54,25 @@ public class SliderPanel extends GSliderPanel
 
   boolean forConservation = true;
 
-  ColourSchemeI cs;
+  ResidueShaderI cs;
+
+  /**
+   * Returns the currently displayed slider panel (or null if none).
+   * 
+   * @return
+   */
+  public static SliderPanel getSliderPanel()
+  {
+    if (conservationSlider != null && conservationSlider.isVisible())
+    {
+      return (SliderPanel) conservationSlider.getContentPane();
+    }
+    if (PIDSlider != null && PIDSlider.isVisible())
+    {
+      return (SliderPanel) PIDSlider.getContentPane();
+    }
+    return null;
+  }
 
   /**
    * Creates a new SliderPanel object.
@@ -64,14 +83,14 @@ public class SliderPanel extends GSliderPanel
    *          DOCUMENT ME!
    * @param forConserve
    *          DOCUMENT ME!
-   * @param cs
+   * @param scheme
    *          DOCUMENT ME!
    */
   public SliderPanel(final AlignmentPanel ap, int value,
-          boolean forConserve, ColourSchemeI cs)
+          boolean forConserve, ResidueShaderI scheme)
   {
     this.ap = ap;
-    this.cs = cs;
+    this.cs = scheme;
     forConservation = forConserve;
     undoButton.setVisible(false);
     applyButton.setVisible(false);
@@ -115,51 +134,52 @@ public class SliderPanel extends GSliderPanel
   }
 
   /**
-   * DOCUMENT ME!
+   * Method to 'set focus' of the Conservation slider panel
    * 
    * @param ap
-   *          DOCUMENT ME!
-   * @param cs
-   *          DOCUMENT ME!
+   *          the panel to repaint on change of slider
+   * @param rs
+   *          the colour scheme to update on change of slider
    * @param source
-   *          DOCUMENT ME!
+   *          a text description for the panel's title
    * 
-   * @return DOCUMENT ME!
+   * @return
    */
   public static int setConservationSlider(AlignmentPanel ap,
-          ColourSchemeI cs, String source)
+          ResidueShaderI rs, String source)
   {
-    SliderPanel sp = null;
+    SliderPanel sliderPanel = null;
 
     if (conservationSlider == null)
     {
-      sp = new SliderPanel(ap, cs.getConservationInc(), true, cs);
+      sliderPanel = new SliderPanel(ap, rs.getConservationInc(), true, rs);
       conservationSlider = new JInternalFrame();
-      conservationSlider.setContentPane(sp);
+      conservationSlider.setContentPane(sliderPanel);
       conservationSlider.setLayer(JLayeredPane.PALETTE_LAYER);
     }
     else
     {
-      sp = (SliderPanel) conservationSlider.getContentPane();
-      sp.valueField.setText(String.valueOf(cs.getConservationInc()));
-      sp.cs = cs;
+      sliderPanel = (SliderPanel) conservationSlider.getContentPane();
+      sliderPanel.valueField.setText(String.valueOf(rs.getConservationInc()));
+      sliderPanel.cs = rs;
+      sliderPanel.ap = ap;
+      sliderPanel.slider.setValue(rs.getConservationInc());
     }
 
-    conservationSlider
-            .setTitle(MessageManager.formatMessage(
-                    "label.conservation_colour_increment",
-                    new String[] { source }));
+    conservationSlider.setTitle(MessageManager.formatMessage(
+            "label.conservation_colour_increment",
+            new String[] { source == null ? BACKGROUND : source }));
 
     if (ap.av.getAlignment().getGroups() != null)
     {
-      sp.setAllGroupsCheckEnabled(true);
+      sliderPanel.setAllGroupsCheckEnabled(true);
     }
     else
     {
-      sp.setAllGroupsCheckEnabled(false);
+      sliderPanel.setAllGroupsCheckEnabled(false);
     }
 
-    return sp.getValue();
+    return sliderPanel.getValue();
   }
 
   /**
@@ -221,59 +241,62 @@ public class SliderPanel extends GSliderPanel
   }
 
   /**
-   * DOCUMENT ME!
+   * Method to 'set focus' of the PID slider panel
    * 
    * @param ap
-   *          DOCUMENT ME!
-   * @param cs
-   *          DOCUMENT ME!
+   *          the panel to repaint on change of slider
+   * @param rs
+   *          the colour scheme to update on change of slider
    * @param source
-   *          DOCUMENT ME!
+   *          a text description for the panel's title
    * 
-   * @return DOCUMENT ME!
+   * @return
    */
-  public static int setPIDSliderSource(AlignmentPanel ap, ColourSchemeI cs,
-          String source)
+  public static int setPIDSliderSource(AlignmentPanel ap,
+          ResidueShaderI rs, String source)
   {
-    SliderPanel pid = null;
+    int threshold = rs.getThreshold();
 
-    int threshold = cs.getThreshold();
+    SliderPanel sliderPanel = null;
 
     if (PIDSlider == null)
     {
-      pid = new SliderPanel(ap, threshold, false, cs);
+      sliderPanel = new SliderPanel(ap, threshold, false, rs);
       PIDSlider = new JInternalFrame();
-      PIDSlider.setContentPane(pid);
+      PIDSlider.setContentPane(sliderPanel);
       PIDSlider.setLayer(JLayeredPane.PALETTE_LAYER);
     }
     else
     {
-      pid = (SliderPanel) PIDSlider.getContentPane();
-      pid.valueField.setText(String.valueOf(cs.getThreshold()));
-      pid.cs = cs;
+      sliderPanel = (SliderPanel) PIDSlider.getContentPane();
+      sliderPanel.cs = rs;
+      sliderPanel.ap = ap;
+      sliderPanel.valueField.setText(String.valueOf(rs.getThreshold()));
+      sliderPanel.slider.setValue(rs.getThreshold());
     }
 
-    PIDSlider
-            .setTitle(MessageManager.formatMessage(
-                    "label.percentage_identity_threshold",
-                    new String[] { source }));
+    PIDSlider.setTitle(MessageManager.formatMessage(
+            "label.percentage_identity_threshold",
+            new String[] { source == null ? BACKGROUND : source }));
 
     if (ap.av.getAlignment().getGroups() != null)
     {
-      pid.setAllGroupsCheckEnabled(true);
+      sliderPanel.setAllGroupsCheckEnabled(true);
     }
     else
     {
-      pid.setAllGroupsCheckEnabled(false);
+      sliderPanel.setAllGroupsCheckEnabled(false);
     }
 
-    return pid.getValue();
+    return sliderPanel.getValue();
   }
 
   /**
    * DOCUMENT ME!
+   * 
+   * @return
    */
-  public static void showPIDSlider()
+  public static JInternalFrame showPIDSlider()
   {
     hideConservationSlider();
 
@@ -292,50 +315,29 @@ public class SliderPanel extends GSliderPanel
       });
       PIDSlider.setLayer(JLayeredPane.PALETTE_LAYER);
     }
+    return PIDSlider;
   }
 
   /**
-   * DOCUMENT ME!
+   * Updates the colour scheme with the current (identity threshold or
+   * conservation) percentage value. Also updates all groups if 'apply to all
+   * groups' is selected.
    * 
-   * @param i
-   *          DOCUMENT ME!
+   * @param percent
    */
-  public void valueChanged(int i)
+  public void valueChanged(int percent)
   {
-    if (cs == null)
+    if (!forConservation)
     {
-      return;
+      ap.av.setThreshold(percent);
     }
-
-    ColourSchemeI toChange = cs;
-    Iterator<SequenceGroup> allGroups = null;
+    updateColourScheme(percent, cs);
 
     if (allGroupsCheck.isSelected())
     {
-      allGroups = ap.av.getAlignment().getGroups().listIterator();
-    }
-
-    while (toChange != null)
-    {
-      if (forConservation)
-      {
-        toChange.setConservationInc(i);
-      }
-      else
-      {
-        toChange.setThreshold(i, ap.av.isIgnoreGapsConsensus());
-      }
-      if (allGroups != null && allGroups.hasNext())
-      {
-        while ((toChange = allGroups.next().cs) == null
-                && allGroups.hasNext())
-        {
-          ;
-        }
-      }
-      else
+      for (SequenceGroup sg : ap.av.getAlignment().getGroups())
       {
-        toChange = null;
+        updateColourScheme(percent, sg.getGroupColourScheme());
       }
     }
 
@@ -343,6 +345,29 @@ public class SliderPanel extends GSliderPanel
   }
 
   /**
+   * Updates the colour scheme (if not null) with the current (identity
+   * threshold or conservation) percentage value
+   * 
+   * @param percent
+   * @param scheme
+   */
+  protected void updateColourScheme(int percent, ResidueShaderI scheme)
+  {
+    if (scheme == null)
+    {
+      return;
+    }
+    if (forConservation)
+    {
+      scheme.setConservationInc(percent);
+    }
+    else
+    {
+      scheme.setThreshold(percent, ap.av.isIgnoreGapsConsensus());
+    }
+  }
+
+  /**
    * DOCUMENT ME!
    * 
    * @param b
@@ -356,6 +381,25 @@ public class SliderPanel extends GSliderPanel
   /**
    * DOCUMENT ME!
    * 
+   * @param e
+   *          DOCUMENT ME!
+   */
+  @Override
+  public void valueField_actionPerformed()
+  {
+    try
+    {
+      int i = Integer.parseInt(valueField.getText());
+      slider.setValue(i);
+    } catch (NumberFormatException ex)
+    {
+      valueField.setText(slider.getValue() + "");
+    }
+  }
+
+  /**
+   * DOCUMENT ME!
+   * 
    * @param value
    *          DOCUMENT ME!
    */
@@ -383,4 +427,53 @@ public class SliderPanel extends GSliderPanel
     }
   }
 
+  public static int getConservationValue()
+  {
+    return getValue(conservationSlider);
+  }
+
+  static int getValue(JInternalFrame slider)
+  {
+    return slider == null ? 0 : ((SliderPanel) slider.getContentPane())
+            .getValue();
+  }
+
+  public static int getPIDValue()
+  {
+    return getValue(PIDSlider);
+  }
+
+  /**
+   * Answers true if the SliderPanel is for Conservation, false if it is for PID
+   * threshold
+   * 
+   * @return
+   */
+  public boolean isForConservation()
+  {
+    return forConservation;
+  }
+
+  /**
+   * Answers the title for the slider panel; this may include 'Background' if
+   * for the alignment, or the group id if for a group
+   * 
+   * @return
+   */
+  public String getTitle()
+  {
+    String title = null;
+    if (isForConservation())
+    {
+      if (conservationSlider != null)
+      {
+        title = conservationSlider.getTitle();
+      }
+    }
+    else if (PIDSlider != null)
+    {
+      title = PIDSlider.getTitle();
+    }
+    return title;
+  }
 }
index 91d7130..34ad659 100644 (file)
  */
 package jalview.gui;
 
+import jalview.bin.Cache;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
 import jalview.gui.StructureViewer.ViewerType;
 import jalview.gui.ViewSelectionMenu.ViewSetProvider;
 import jalview.io.DataSourceType;
+import jalview.io.JalviewFileChooser;
+import jalview.io.JalviewFileView;
 import jalview.jbgui.GStructureViewer;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ColourSchemes;
 import jalview.structures.models.AAStructureBindingModel;
 import jalview.util.MessageManager;
 
+import java.awt.Color;
 import java.awt.Component;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 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.JRadioButtonMenuItem;
+import javax.swing.event.MenuEvent;
+import javax.swing.event.MenuListener;
 
 /**
  * Base class with common functionality for JMol, Chimera or other structure
@@ -52,6 +72,13 @@ import javax.swing.JOptionPane;
 public abstract class StructureViewerBase extends GStructureViewer
         implements Runnable, ViewSetProvider
 {
+  /*
+   * names for colour options (additional to Jalview colour schemes)
+   */
+  enum ViewerColour
+  {
+    BySequence, ByChain, ChargeCysteine, ByViewer
+  }
 
   /**
    * list of sequenceSet ids associated with the view
@@ -84,6 +111,13 @@ public abstract class StructureViewerBase extends GStructureViewer
   protected boolean allChainsSelected = false;
 
   /**
+   * Default constructor
+   */
+  public StructureViewerBase()
+  {
+    super();
+  }
+  /**
    * 
    * @param ap2
    * @return true if this Jmol instance is linked with the given alignPanel
@@ -273,8 +307,6 @@ public abstract class StructureViewerBase extends GStructureViewer
 
   public abstract ViewerType getViewerType();
 
-  protected abstract AAStructureBindingModel getBindingModel();
-
   /**
    * add a new structure (with associated sequences and chains) to this viewer,
    * retrieving it if necessary first.
@@ -320,7 +352,7 @@ public abstract class StructureViewerBase extends GStructureViewer
       }
     }
     // otherwise, start adding the structure.
-    getBindingModel().addSequenceAndChain(new PDBEntry[] { pdbentry },
+    getBinding().addSequenceAndChain(new PDBEntry[] { pdbentry },
             new SequenceI[][] { seqs }, new String[][] { chains });
     addingStructures = true;
     _started = false;
@@ -350,7 +382,10 @@ public abstract class StructureViewerBase extends GStructureViewer
     return option;
   }
 
-  protected abstract boolean hasPdbId(String pdbId);
+  protected boolean hasPdbId(String pdbId)
+  {
+    return getBinding().hasPdbId(pdbId);
+  }
 
   protected abstract List<StructureViewerBase> getViewersFor(
           AlignmentPanel alp);
@@ -438,7 +473,7 @@ public abstract class StructureViewerBase extends GStructureViewer
     // JBPNOTE: this looks like a binding routine, rather than a gui routine
     for (StructureViewerBase viewer : getViewersFor(null))
     {
-      AAStructureBindingModel bindingModel = viewer.getBindingModel();
+      AAStructureBindingModel bindingModel = viewer.getBinding();
       for (int pe = 0; pe < bindingModel.getPdbCount(); pe++)
       {
         if (bindingModel.getPdbEntry(pe).getFile().equals(pdbFilename))
@@ -552,4 +587,389 @@ public abstract class StructureViewerBase extends GStructureViewer
 
   abstract void showSelectedChains();
 
+  /**
+   * Action on selecting one of Jalview's registered colour schemes
+   */
+  @Override
+  public void changeColour_actionPerformed(String colourSchemeName)
+  {
+    AlignmentI al = getAlignmentPanel().av.getAlignment();
+    ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(
+            colourSchemeName, al, null);
+    getBinding().setJalviewColourScheme(cs);
+  }
+
+  /**
+   * Builds the colour menu
+   */
+  protected void buildColourMenu()
+  {
+    colourMenu.removeAll();
+    AlignmentI al = getAlignmentPanel().av.getAlignment();
+
+    /*
+     * add colour by sequence, by chain, by charge and cysteine
+     */
+    colourMenu.add(seqColour);
+    colourMenu.add(chainColour);
+    colourMenu.add(chargeColour);
+    chargeColour.setEnabled(!al.isNucleotide());
+
+    /*
+     * add all 'simple' (per-residue) colour schemes registered to Jalview
+     */
+    ButtonGroup itemGroup = ColourMenuHelper.addMenuItems(colourMenu, this,
+            al, true);
+
+    /*
+     * add 'colour by viewer' (menu item text is set in subclasses)
+     */
+    viewerColour.setSelected(false);
+    viewerColour.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent actionEvent)
+      {
+        viewerColour_actionPerformed(actionEvent);
+      }
+    });
+    colourMenu.add(viewerColour);
+
+    /*
+     * add 'set background colour'
+     */
+    JMenuItem backGround = new JMenuItem();
+    backGround
+            .setText(MessageManager.getString("action.background_colour"));
+    backGround.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent actionEvent)
+      {
+        background_actionPerformed(actionEvent);
+      }
+    });
+    colourMenu.add(backGround);
+
+    /*
+     * add colour buttons to a group so their selection is
+     * mutually exclusive (background colour is a separate option)
+     */
+    itemGroup.add(seqColour);
+    itemGroup.add(chainColour);
+    itemGroup.add(chargeColour);
+    itemGroup.add(viewerColour);
+  }
+
+  /**
+   * Construct menu items
+   */
+  protected void initMenus()
+  {
+    AAStructureBindingModel binding = getBinding();
+
+    seqColour = new JRadioButtonMenuItem();
+    seqColour.setText(MessageManager.getString("action.by_sequence"));
+    seqColour.setName(ViewerColour.BySequence.name());
+    seqColour.setSelected(binding.isColourBySequence());
+    seqColour.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent actionEvent)
+      {
+        seqColour_actionPerformed(actionEvent);
+      }
+    });
+
+    chainColour = new JRadioButtonMenuItem();
+    chainColour.setText(MessageManager.getString("action.by_chain"));
+    chainColour.setName(ViewerColour.ByChain.name());
+    chainColour.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent actionEvent)
+      {
+        chainColour_actionPerformed(actionEvent);
+      }
+    });
+
+    chargeColour = new JRadioButtonMenuItem();
+    chargeColour.setText(MessageManager.getString("label.charge_cysteine"));
+    chargeColour.setName(ViewerColour.ChargeCysteine.name());
+    chargeColour.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent actionEvent)
+      {
+        chargeColour_actionPerformed(actionEvent);
+      }
+    });
+
+    viewerColour = new JRadioButtonMenuItem();
+    // text is set in overrides of this method
+    viewerColour.setName(ViewerColour.ByViewer.name());
+    viewerColour.setSelected(!binding.isColourBySequence());
+
+    if (_colourwith == null)
+    {
+      _colourwith = new Vector<AlignmentPanel>();
+    }
+    if (_alignwith == null)
+    {
+      _alignwith = new Vector<AlignmentPanel>();
+    }
+
+    ViewSelectionMenu seqColourBy = new ViewSelectionMenu(
+            MessageManager.getString("label.colour_by"), this, _colourwith,
+            new ItemListener()
+            {
+              @Override
+              public void itemStateChanged(ItemEvent e)
+              {
+                if (!seqColour.isSelected())
+                {
+                  seqColour.doClick();
+                }
+                else
+                {
+                  // update the Chimera display now.
+                  seqColour_actionPerformed(null);
+                }
+              }
+            });
+    viewMenu.add(seqColourBy);
+
+    final ItemListener handler = new ItemListener()
+    {
+      @Override
+      public void itemStateChanged(ItemEvent e)
+      {
+        alignStructs.setEnabled(_alignwith.size() > 0);
+        alignStructs.setToolTipText(MessageManager.formatMessage(
+                "label.align_structures_using_linked_alignment_views",
+                new String[] { String.valueOf(_alignwith.size()) }));
+      }
+    };
+    JMenu alpanels = new ViewSelectionMenu(
+            MessageManager.getString("label.superpose_with"), this,
+            _alignwith, handler);
+    handler.itemStateChanged(null);
+    viewerActionMenu.add(alpanels);
+    viewerActionMenu.addMenuListener(new MenuListener()
+    {
+      @Override
+      public void menuSelected(MenuEvent e)
+      {
+        handler.itemStateChanged(null);
+      }
+
+      @Override
+      public void menuDeselected(MenuEvent e)
+      {
+      }
+
+      @Override
+      public void menuCanceled(MenuEvent e)
+      {
+      }
+    });
+
+    buildColourMenu();
+  }
+
+  @Override
+  public void setJalviewColourScheme(ColourSchemeI cs) {
+    getBinding().setJalviewColourScheme(cs);
+  }
+  @Override
+  protected void alignStructs_actionPerformed(ActionEvent actionEvent)
+  {
+    alignStructs_withAllAlignPanels();
+  }
+  protected void alignStructs_withAllAlignPanels()
+  {
+    if (getAlignmentPanel() == null)
+    {
+      return;
+    }
+  
+    if (_alignwith.size() == 0)
+    {
+      _alignwith.add(getAlignmentPanel());
+    }
+  
+    try
+    {
+      AlignmentI[] als = new Alignment[_alignwith.size()];
+      ColumnSelection[] alc = new ColumnSelection[_alignwith.size()];
+      int[] alm = new int[_alignwith.size()];
+      int a = 0;
+  
+      for (AlignmentPanel ap : _alignwith)
+      {
+        als[a] = ap.av.getAlignment();
+        alm[a] = -1;
+        alc[a++] = ap.av.getColumnSelection();
+      }
+      getBinding().superposeStructures(als, alm, alc);
+    } catch (Exception e)
+    {
+      StringBuffer sp = new StringBuffer();
+      for (AlignmentPanel ap : _alignwith)
+      {
+        sp.append("'" + ap.alignFrame.getTitle() + "' ");
+      }
+      Cache.log.info("Couldn't align structures with the " + sp.toString()
+              + "associated alignment panels.", e);
+    }
+  }
+  @Override
+  public void background_actionPerformed(ActionEvent actionEvent)
+  {
+    Color col = JColorChooser.showDialog(this,
+            MessageManager.getString("label.select_background_colour"),
+            null);
+    if (col != null)
+    {
+      getBinding().setBackgroundColour(col);
+    }
+  }
+  @Override
+  public void viewerColour_actionPerformed(ActionEvent actionEvent)
+  {
+    if (viewerColour.isSelected())
+    {
+      // disable automatic sequence colouring.
+      getBinding().setColourBySequence(false);
+    }
+  }
+  @Override
+  public void chainColour_actionPerformed(ActionEvent actionEvent)
+  {
+    chainColour.setSelected(true);
+    getBinding().colourByChain();
+  }
+  @Override
+  public void chargeColour_actionPerformed(ActionEvent actionEvent)
+  {
+    chargeColour.setSelected(true);
+    getBinding().colourByCharge();
+  }
+  @Override
+  public void seqColour_actionPerformed(ActionEvent actionEvent)
+  {
+    AAStructureBindingModel binding = getBinding();
+    binding.setColourBySequence(seqColour.isSelected());
+    if (_colourwith == null)
+    {
+      _colourwith = new Vector<AlignmentPanel>();
+    }
+    if (binding.isColourBySequence())
+    {
+      if (!binding.isLoadingFromArchive())
+      {
+        if (_colourwith.size() == 0 && getAlignmentPanel() != null)
+        {
+          // Make the currently displayed alignment panel the associated view
+          _colourwith.add(getAlignmentPanel().alignFrame.alignPanel);
+        }
+      }
+      // Set the colour using the current view for the associated alignframe
+      for (AlignmentPanel ap : _colourwith)
+      {
+        binding.colourBySequence(ap);
+      }
+    }
+  }
+  @Override
+  public void pdbFile_actionPerformed(ActionEvent actionEvent)
+  {
+    JalviewFileChooser chooser = new JalviewFileChooser(
+            Cache.getProperty("LAST_DIRECTORY"));
+  
+    chooser.setFileView(new JalviewFileView());
+    chooser.setDialogTitle(MessageManager.getString("label.save_pdb_file"));
+    chooser.setToolTipText(MessageManager.getString("action.save"));
+  
+    int value = chooser.showSaveDialog(this);
+  
+    if (value == JalviewFileChooser.APPROVE_OPTION)
+    {
+      BufferedReader in = null;
+      try
+      {
+        // TODO: cope with multiple PDB files in view
+        in = new BufferedReader(
+                new FileReader(getBinding().getPdbFile()[0]));
+        File outFile = chooser.getSelectedFile();
+  
+        PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
+        String data;
+        while ((data = in.readLine()) != null)
+        {
+          if (!(data.indexOf("<PRE>") > -1 || data.indexOf("</PRE>") > -1))
+          {
+            out.println(data);
+          }
+        }
+        out.close();
+      } catch (Exception ex)
+      {
+        ex.printStackTrace();
+      } finally
+      {
+        if (in != null)
+        {
+          try
+          {
+            in.close();
+          } catch (IOException e)
+          {
+            // ignore
+          }
+        }
+      }
+    }
+  }
+  @Override
+  public void viewMapping_actionPerformed(ActionEvent actionEvent)
+  {
+    CutAndPasteTransfer cap = new CutAndPasteTransfer();
+    try
+    {
+      cap.appendText(getBinding().printMappings());
+    } catch (OutOfMemoryError e)
+    {
+      new OOMWarning(
+              "composing sequence-structure alignments for display in text box.",
+              e);
+      cap.dispose();
+      return;
+    }
+    Desktop.addInternalFrame(cap,
+            MessageManager.getString("label.pdb_sequence_mapping"), 550,
+            600);
+  }
+
+  protected abstract String getViewerName();
+  public void updateTitleAndMenus()
+  {
+    AAStructureBindingModel binding = getBinding();
+    if (binding.hasFileLoadingError())
+    {
+      repaint();
+      return;
+    }
+    setChainMenuItems(binding.getChainNames());
+  
+    this.setTitle(binding.getViewerTitle(getViewerName(), true));
+    if (binding.getPdbFile().length > 1 && binding.getSequence().length > 1)
+    {
+      viewerActionMenu.setVisible(true);
+    }
+    if (!binding.isLoadingFromArchive())
+    {
+      seqColour_actionPerformed(null);
+    }
+  }
 }
index 84fd82f..54eed1a 100755 (executable)
@@ -997,17 +997,21 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
         }
         else
         {
-          cs = ColourSchemeProperty.getColour(sg, ColourSchemeProperty
-                  .getColourName(av.getGlobalColourScheme()));
+          cs = ColourSchemeProperty.getColourScheme(sg,
+                  ColourSchemeProperty.getColourName(av
+                          .getGlobalColourScheme()));
         }
         // cs is null if shading is an annotationColourGradient
-        if (cs != null)
-        {
-          cs.setThreshold(av.getGlobalColourScheme().getThreshold(),
-                  av.isIgnoreGapsConsensus());
-        }
+        // if (cs != null)
+        // {
+        // cs.setThreshold(av.getViewportColourScheme().getThreshold(),
+        // av.isIgnoreGapsConsensus());
+        // }
       }
-      sg.cs = cs;
+      sg.setColourScheme(cs);
+      sg.getGroupColourScheme().setThreshold(
+              av.getResidueShading().getThreshold(),
+              av.isIgnoreGapsConsensus());
       // sg.recalcConservation();
       sg.setName("JTreeGroup:" + sg.hashCode());
       sg.setIdColour(col);
@@ -1015,7 +1019,8 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
       for (int a = 0; a < aps.length; a++)
       {
         if (aps[a].av.getGlobalColourScheme() != null
-                && aps[a].av.getGlobalColourScheme().conservationApplied())
+                && aps[a].av.getResidueShading()
+                        .conservationApplied())
         {
           Conservation c = new Conservation("Group", sg.getSequences(null),
                   sg.getStartRes(), sg.getEndRes());
index 6b4bd10..10a9687 100755 (executable)
 package jalview.gui;
 
 import jalview.api.structures.JalviewStructureDisplayI;
+import jalview.bin.Cache;
 import jalview.datamodel.SequenceGroup;
 import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
 import jalview.jbgui.GUserDefinedColours;
+import jalview.schemabinding.version2.Colour;
+import jalview.schemabinding.version2.JalviewUserColours;
 import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ColourSchemes;
 import jalview.schemes.ResidueProperties;
 import jalview.schemes.UserColourScheme;
 import jalview.util.ColorUtils;
+import jalview.util.Format;
 import jalview.util.MessageManager;
 
 import java.awt.Color;
 import java.awt.Font;
+import java.awt.Insets;
 import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileOutputStream;
-import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.StringTokenizer;
+import java.util.List;
 
 import javax.swing.JButton;
 import javax.swing.JInternalFrame;
@@ -60,6 +64,13 @@ import javax.swing.event.ChangeListener;
 public class UserDefinedColours extends GUserDefinedColours implements
         ChangeListener
 {
+  private static final Font VERDANA_BOLD_10 = new Font("Verdana",
+          Font.BOLD, 10);
+
+  public static final String USER_DEFINED_COLOURS = "USER_DEFINED_COLOURS";
+
+  private static final String LAST_DIRECTORY = "LAST_DIRECTORY";
+
   private static final int MY_FRAME_HEIGHT = 420;
 
   private static final int MY_FRAME_WIDTH = 810;
@@ -70,29 +81,27 @@ public class UserDefinedColours extends GUserDefinedColours implements
 
   SequenceGroup seqGroup;
 
-  ArrayList<JButton> selectedButtons;
+  List<JButton> selectedButtons;
 
   ColourSchemeI oldColourScheme;
 
   JInternalFrame frame;
 
-  JalviewStructureDisplayI jmol;
+  JalviewStructureDisplayI structureViewer;
 
-  ArrayList<JButton> upperCaseButtons;
+  List<JButton> upperCaseButtons;
 
-  ArrayList<JButton> lowerCaseButtons;
+  List<JButton> lowerCaseButtons;
 
   /**
    * Creates a new UserDefinedColours object.
    * 
    * @param ap
-   *          DOCUMENT ME!
    * @param sg
-   *          DOCUMENT ME!
    */
   public UserDefinedColours(AlignmentPanel ap, SequenceGroup sg)
   {
-    super();
+    this();
 
     lcaseColour.setEnabled(false);
 
@@ -101,7 +110,7 @@ public class UserDefinedColours extends GUserDefinedColours implements
 
     if (seqGroup != null)
     {
-      oldColourScheme = seqGroup.cs;
+      oldColourScheme = seqGroup.getColourScheme();
     }
     else
     {
@@ -110,11 +119,12 @@ public class UserDefinedColours extends GUserDefinedColours implements
 
     if (oldColourScheme instanceof UserColourScheme)
     {
-      schemeName.setText(((UserColourScheme) oldColourScheme).getName());
+      schemeName.setText(oldColourScheme.getSchemeName());
       if (((UserColourScheme) oldColourScheme).getLowerCaseColours() != null)
       {
         caseSensitive.setSelected(true);
         lcaseColour.setEnabled(true);
+        lcaseColour.setForeground(Color.GRAY);
         resetButtonPanel(true);
       }
       else
@@ -130,11 +140,11 @@ public class UserDefinedColours extends GUserDefinedColours implements
     showFrame();
   }
 
-  public UserDefinedColours(JalviewStructureDisplayI jmol,
+  public UserDefinedColours(JalviewStructureDisplayI viewer,
           ColourSchemeI oldcs)
   {
-    super();
-    this.jmol = jmol;
+    this();
+    this.structureViewer = viewer;
 
     colorChooser.getSelectionModel().addChangeListener(this);
 
@@ -142,7 +152,8 @@ public class UserDefinedColours extends GUserDefinedColours implements
 
     if (oldColourScheme instanceof UserColourScheme)
     {
-      schemeName.setText(((UserColourScheme) oldColourScheme).getName());
+      schemeName.setText(((UserColourScheme) oldColourScheme)
+              .getSchemeName());
     }
 
     resetButtonPanel(false);
@@ -151,6 +162,12 @@ public class UserDefinedColours extends GUserDefinedColours implements
 
   }
 
+  public UserDefinedColours()
+  {
+    super();
+    selectedButtons = new ArrayList<JButton>();
+  }
+
   void showFrame()
   {
     colorChooser.getSelectionModel().addChangeListener(this);
@@ -166,7 +183,15 @@ public class UserDefinedColours extends GUserDefinedColours implements
     }
   }
 
-  void resetButtonPanel(boolean caseSensitive)
+  /**
+   * Rebuilds the panel with coloured buttons for residues. If not case
+   * sensitive colours, show 3-letter amino acid code as button text. If case
+   * sensitive, just show the single letter code, in order to make space for the
+   * additional buttons.
+   * 
+   * @param isCaseSensitive
+   */
+  void resetButtonPanel(boolean isCaseSensitive)
   {
     buttonPanel.removeAll();
 
@@ -175,23 +200,13 @@ public class UserDefinedColours extends GUserDefinedColours implements
       upperCaseButtons = new ArrayList<JButton>();
     }
 
-    JButton button;
-    String label;
     for (int i = 0; i < 20; i++)
     {
-      if (caseSensitive)
-      {
-        label = ResidueProperties.aa[i];
-      }
-      else
-      {
-        label = ResidueProperties.aa2Triplet.get(ResidueProperties.aa[i])
-                .toString();
-      }
-
-      button = makeButton(label, ResidueProperties.aa[i], upperCaseButtons,
-              i);
-
+      String label = isCaseSensitive ? ResidueProperties.aa[i]
+              : ResidueProperties.aa2Triplet.get(ResidueProperties.aa[i])
+                      .toString();
+      JButton button = makeButton(label, ResidueProperties.aa[i],
+              upperCaseButtons, i);
       buttonPanel.add(button);
     }
 
@@ -200,7 +215,7 @@ public class UserDefinedColours extends GUserDefinedColours implements
     buttonPanel.add(makeButton("X", "X", upperCaseButtons, 22));
     buttonPanel.add(makeButton("Gap", "-", upperCaseButtons, 23));
 
-    if (!caseSensitive)
+    if (!isCaseSensitive)
     {
       gridLayout.setRows(6);
       gridLayout.setColumns(4);
@@ -220,14 +235,14 @@ public class UserDefinedColours extends GUserDefinedColours implements
       {
         int row = i / cols + 1;
         int index = (row * cols) + i;
-        button = makeButton(ResidueProperties.aa[i].toLowerCase(),
+        JButton button = makeButton(ResidueProperties.aa[i].toLowerCase(),
                 ResidueProperties.aa[i].toLowerCase(), lowerCaseButtons, i);
 
         buttonPanel.add(button, index);
       }
     }
 
-    if (caseSensitive)
+    if (isCaseSensitive)
     {
       buttonPanel.add(makeButton("b", "b", lowerCaseButtons, 20));
       buttonPanel.add(makeButton("z", "z", lowerCaseButtons, 21));
@@ -238,7 +253,7 @@ public class UserDefinedColours extends GUserDefinedColours implements
     // codes
     if (this.frame != null)
     {
-      int newWidth = caseSensitive ? MY_FRAME_WIDTH_CASE_SENSITIVE
+      int newWidth = isCaseSensitive ? MY_FRAME_WIDTH_CASE_SENSITIVE
               : MY_FRAME_WIDTH;
       this.frame.setSize(newWidth, this.frame.getHeight());
     }
@@ -248,33 +263,34 @@ public class UserDefinedColours extends GUserDefinedColours implements
   }
 
   /**
-   * DOCUMENT ME!
+   * ChangeListener handler for when a colour is picked in the colour chooser.
+   * The action is to apply the colour to all selected buttons as their
+   * background colour. Foreground colour (text) is set to a lighter shade in
+   * order to highlight which buttons are selected. If 'Lower Case Colour' is
+   * active, then the colour is applied to all lower case buttons (as well as
+   * the Lower Case Colour button itself).
    * 
    * @param evt
-   *          DOCUMENT ME!
    */
   @Override
   public void stateChanged(ChangeEvent evt)
   {
-    if (selectedButtons != null)
+    JButton button = null;
+    final Color newColour = colorChooser.getColor();
+    for (int i = 0; i < selectedButtons.size(); i++)
     {
-      JButton button = null;
-      final Color newColour = colorChooser.getColor();
-      for (int i = 0; i < selectedButtons.size(); i++)
+      button = selectedButtons.get(i);
+      button.setBackground(newColour);
+      button.setForeground(ColorUtils.brighterThan(newColour));
+    }
+    if (button == lcaseColour)
+    {
+      button.setForeground(Color.black);
+      for (int i = 0; i < lowerCaseButtons.size(); i++)
       {
-        button = selectedButtons.get(i);
+        button = lowerCaseButtons.get(i);
         button.setBackground(newColour);
-        button.setForeground(ColorUtils.brighterThan(newColour));
-      }
-      if (button == lcaseColour)
-      {
-        for (int i = 0; i < lowerCaseButtons.size(); i++)
-        {
-          button = lowerCaseButtons.get(i);
-          button.setBackground(newColour);
-          button.setForeground(ColorUtils.brighterThan(button
-                  .getBackground()));
-        }
+        button.setForeground(ColorUtils.brighterThan(button.getBackground()));
       }
     }
   }
@@ -299,11 +315,6 @@ public class UserDefinedColours extends GUserDefinedColours implements
    */
   public void colourButtonPressed(MouseEvent e)
   {
-    if (selectedButtons == null)
-    {
-      selectedButtons = new ArrayList<JButton>();
-    }
-
     JButton pressed = (JButton) e.getSource();
 
     if (e.isShiftDown())
@@ -383,28 +394,35 @@ public class UserDefinedColours extends GUserDefinedColours implements
   }
 
   /**
-   * DOCUMENT ME!
+   * A helper method to update or make a colour button, whose background colour
+   * is the associated colour, and text colour a darker shade of the same. If
+   * the button is already in the list, then its text and margins are updated,
+   * if not then it is created and added. This method supports toggling between
+   * case-sensitive and case-insensitive button panels. The case-sensitive
+   * version has abbreviated button text in order to fit in more buttons.
    * 
    * @param label
-   *          DOCUMENT ME!
-   * @param aa
-   *          DOCUMENT ME!
+   * @param residue
+   * @param the
+   *          list of buttons
+   * @param buttonIndex
+   *          the button's position in the list
    */
-  JButton makeButton(String label, String aa,
-          ArrayList<JButton> caseSensitiveButtons, int buttonIndex)
+  JButton makeButton(String label, String residue, List<JButton> buttons,
+          int buttonIndex)
   {
     final JButton button;
     Color col;
 
-    if (buttonIndex < caseSensitiveButtons.size())
+    if (buttonIndex < buttons.size())
     {
-      button = caseSensitiveButtons.get(buttonIndex);
+      button = buttons.get(buttonIndex);
       col = button.getBackground();
     }
     else
     {
       button = new JButton();
-      button.addMouseListener(new java.awt.event.MouseAdapter()
+      button.addMouseListener(new MouseAdapter()
       {
         @Override
         public void mouseClicked(MouseEvent e)
@@ -413,46 +431,45 @@ public class UserDefinedColours extends GUserDefinedColours implements
         }
       });
 
-      caseSensitiveButtons.add(button);
+      buttons.add(button);
 
+      /*
+       * make initial button colour that of the current colour scheme,
+       * if it is a simple per-residue colouring, else white
+       */
       col = Color.white;
-      if (oldColourScheme != null)
+      if (oldColourScheme != null && oldColourScheme.isSimple())
       {
-        try
-        {
-          col = oldColourScheme.findColour(aa.charAt(0), -1, null);
-        } catch (Exception ex)
-        {
-        }
+        col = oldColourScheme.findColour(residue.charAt(0), 0, null, null,
+                0f);
       }
     }
 
     if (caseSensitive.isSelected())
     {
-      button.setMargin(new java.awt.Insets(2, 2, 2, 2));
+      button.setMargin(new Insets(2, 2, 2, 2));
     }
     else
     {
-      button.setMargin(new java.awt.Insets(2, 14, 2, 14));
+      button.setMargin(new Insets(2, 14, 2, 14));
     }
 
     button.setOpaque(true); // required for the next line to have effect
     button.setBackground(col);
     button.setText(label);
     button.setForeground(ColorUtils.darkerThan(col));
-    button.setFont(new java.awt.Font("Verdana", Font.BOLD, 10));
+    button.setFont(VERDANA_BOLD_10);
 
     return button;
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
+   * On 'OK', check that at least one colour has been assigned to a residue (and
+   * if not issue a warning), and apply the chosen colour scheme and close the
+   * panel.
    */
   @Override
-  protected void okButton_actionPerformed(ActionEvent e)
+  protected void okButton_actionPerformed()
   {
     if (isNoSelectionMade())
     {
@@ -463,7 +480,7 @@ public class UserDefinedColours extends GUserDefinedColours implements
     }
     else
     {
-      applyButton_actionPerformed(null);
+      applyButton_actionPerformed();
 
       try
       {
@@ -492,13 +509,11 @@ public class UserDefinedColours extends GUserDefinedColours implements
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
+   * Applies the current colour scheme to the alignment, sequence group or
+   * structure view.
    */
   @Override
-  protected void applyButton_actionPerformed(ActionEvent e)
+  protected void applyButton_actionPerformed()
   {
     if (isNoSelectionMade())
     {
@@ -509,20 +524,19 @@ public class UserDefinedColours extends GUserDefinedColours implements
 
     }
     UserColourScheme ucs = getSchemeFromButtons();
-    ucs.setName(schemeName.getText());
 
     if (seqGroup != null)
     {
-      seqGroup.cs = ucs;
+      seqGroup.setColourScheme(ucs);
       ap.paintAlignment(true);
     }
     else if (ap != null)
     {
       ap.alignFrame.changeColour(ucs);
     }
-    else if (jmol != null)
+    else if (structureViewer != null)
     {
-      jmol.setJalviewColourScheme(ucs);
+      structureViewer.setJalviewColourScheme(ucs);
     }
   }
 
@@ -551,6 +565,7 @@ public class UserDefinedColours extends GUserDefinedColours implements
     }
 
     UserColourScheme ucs = new UserColourScheme(newColours);
+    ucs.setName(schemeName.getText());
 
     if (caseSensitive.isSelected())
     {
@@ -576,10 +591,10 @@ public class UserDefinedColours extends GUserDefinedColours implements
       ucs.setLowerCaseColours(newColours);
     }
 
-    if (ap != null)
-    {
-      ucs.setThreshold(0, ap.av.isIgnoreGapsConsensus());
-    }
+    // if (ap != null)
+    // {
+    // ucs.setThreshold(0, ap.av.isIgnoreGapsConsensus());
+    // }
 
     return ucs;
   }
@@ -605,80 +620,69 @@ public class UserDefinedColours extends GUserDefinedColours implements
 
     int value = chooser.showOpenDialog(this);
 
-    if (value == JalviewFileChooser.APPROVE_OPTION)
+    if (value != JalviewFileChooser.APPROVE_OPTION)
     {
-      File choice = chooser.getSelectedFile();
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
-      String defaultColours = jalview.bin.Cache.getDefault(
-              "USER_DEFINED_COLOURS", choice.getPath());
-      if (defaultColours.indexOf(choice.getPath()) == -1)
-      {
-        defaultColours = defaultColours.concat("|")
-                .concat(choice.getPath());
-      }
-
-      jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS", defaultColours);
-
-      UserColourScheme ucs = loadColours(choice.getAbsolutePath());
-      Color[] colors = ucs.getColours();
-      schemeName.setText(ucs.getName());
-
-      if (ucs.getLowerCaseColours() != null)
-      {
-        caseSensitive.setSelected(true);
-        lcaseColour.setEnabled(true);
-        resetButtonPanel(true);
-        for (int i = 0; i < lowerCaseButtons.size(); i++)
-        {
-          JButton button = lowerCaseButtons.get(i);
-          button.setBackground(ucs.getLowerCaseColours()[i]);
-        }
+      return;
+    }
+    File choice = chooser.getSelectedFile();
+    Cache.setProperty(LAST_DIRECTORY, choice.getParent());
 
-      }
-      else
-      {
-        caseSensitive.setSelected(false);
-        lcaseColour.setEnabled(false);
-        resetButtonPanel(false);
-      }
+    UserColourScheme ucs = ColourSchemes.loadColourScheme(choice
+            .getAbsolutePath());
+    Color[] colors = ucs.getColours();
+    schemeName.setText(ucs.getSchemeName());
 
-      for (int i = 0; i < upperCaseButtons.size(); i++)
+    if (ucs.getLowerCaseColours() != null)
+    {
+      caseSensitive.setSelected(true);
+      lcaseColour.setEnabled(true);
+      lcaseColour.setForeground(Color.GRAY);
+      resetButtonPanel(true);
+      for (int i = 0; i < lowerCaseButtons.size(); i++)
       {
-        JButton button = upperCaseButtons.get(i);
-        button.setBackground(colors[i]);
+        JButton button = lowerCaseButtons.get(i);
+        button.setBackground(ucs.getLowerCaseColours()[i]);
       }
+    }
+    else
+    {
+      caseSensitive.setSelected(false);
+      lcaseColour.setEnabled(false);
+      resetButtonPanel(false);
+    }
 
+    for (int i = 0; i < upperCaseButtons.size(); i++)
+    {
+      JButton button = upperCaseButtons.get(i);
+      button.setBackground(colors[i]);
     }
+
+    addNewColourScheme(choice.getPath());
   }
 
   /**
-   * DOCUMENT ME!
+   * Loads the user-defined colour scheme from the first file listed in property
+   * "USER_DEFINED_COLOURS". If this fails, returns an all-white colour scheme.
    * 
-   * @return DOCUMENT ME!
+   * @return
    */
   public static UserColourScheme loadDefaultColours()
   {
     UserColourScheme ret = null;
 
-    String colours = jalview.bin.Cache.getProperty("USER_DEFINED_COLOURS");
+    String colours = Cache.getProperty(USER_DEFINED_COLOURS);
     if (colours != null)
     {
       if (colours.indexOf("|") > -1)
       {
         colours = colours.substring(0, colours.indexOf("|"));
       }
-
-      ret = loadColours(colours);
+      ret = ColourSchemes.loadColourScheme(colours);
     }
 
     if (ret == null)
     {
-      Color[] newColours = new Color[24];
-      for (int i = 0; i < 24; i++)
-      {
-        newColours[i] = Color.white;
-      }
-      ret = new UserColourScheme(newColours);
+      ret = new UserColourScheme("white");
     }
 
     return ret;
@@ -687,125 +691,14 @@ public class UserDefinedColours extends GUserDefinedColours implements
   /**
    * DOCUMENT ME!
    * 
-   * @param file
-   *          DOCUMENT ME!
-   * 
-   * @return DOCUMENT ME!
-   */
-  static UserColourScheme loadColours(String file)
-  {
-    UserColourScheme ucs = null;
-    Color[] newColours = null;
-    try
-    {
-      InputStreamReader in = new InputStreamReader(
-              new FileInputStream(file), "UTF-8");
-
-      jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
-
-      org.exolab.castor.xml.Unmarshaller unmar = new org.exolab.castor.xml.Unmarshaller(
-              jucs);
-      jucs = (jalview.schemabinding.version2.JalviewUserColours) unmar
-              .unmarshal(in);
-
-      newColours = new Color[24];
-
-      Color[] lowerCase = null;
-      boolean caseSensitive = false;
-
-      String name;
-      int index;
-      for (int i = 0; i < jucs.getColourCount(); i++)
-      {
-        name = jucs.getColour(i).getName();
-        if (ResidueProperties.aa3Hash.containsKey(name))
-        {
-          index = ResidueProperties.aa3Hash.get(name).intValue();
-        }
-        else
-        {
-          index = ResidueProperties.aaIndex[name.charAt(0)];
-        }
-        if (index == -1)
-        {
-          continue;
-        }
-
-        if (name.toLowerCase().equals(name))
-        {
-          if (lowerCase == null)
-          {
-            lowerCase = new Color[23];
-          }
-          caseSensitive = true;
-          lowerCase[index] = new Color(Integer.parseInt(jucs.getColour(i)
-                  .getRGB(), 16));
-        }
-        else
-        {
-          newColours[index] = new Color(Integer.parseInt(jucs.getColour(i)
-                  .getRGB(), 16));
-        }
-      }
-
-      if (newColours != null)
-      {
-        ucs = new UserColourScheme(newColours);
-        ucs.setName(jucs.getSchemeName());
-        if (caseSensitive)
-        {
-          ucs.setLowerCaseColours(lowerCase);
-        }
-      }
-
-    } catch (Exception ex)
-    {
-      // Could be Archive Jalview format
-      try
-      {
-        InputStreamReader in = new InputStreamReader(new FileInputStream(
-                file), "UTF-8");
-
-        jalview.binding.JalviewUserColours jucs = new jalview.binding.JalviewUserColours();
-
-        jucs = jucs.unmarshal(in);
-
-        newColours = new Color[jucs.getColourCount()];
-
-        for (int i = 0; i < 24; i++)
-        {
-          newColours[i] = new Color(Integer.parseInt(jucs.getColour(i)
-                  .getRGB(), 16));
-        }
-        if (newColours != null)
-        {
-          ucs = new UserColourScheme(newColours);
-          ucs.setName(jucs.getSchemeName());
-        }
-      } catch (Exception ex2)
-      {
-        ex2.printStackTrace();
-      }
-
-      if (newColours == null)
-      {
-        System.out.println("Error loading User ColourFile\n" + ex);
-      }
-    }
-
-    return ucs;
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
    * @param e
    *          DOCUMENT ME!
    */
   @Override
   protected void savebutton_actionPerformed(ActionEvent e)
   {
-    if (schemeName.getText().trim().length() < 1)
+    String name = schemeName.getText().trim();
+    if (name.length() < 1)
     {
       JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
               .getString("label.user_colour_scheme_must_have_name"),
@@ -814,26 +707,25 @@ public class UserDefinedColours extends GUserDefinedColours implements
       return;
     }
 
-    if (userColourSchemes != null
-            && userColourSchemes.containsKey(schemeName.getText()))
+    if (ColourSchemes.getInstance().nameExists(name))
     {
       int reply = JvOptionPane.showInternalConfirmDialog(Desktop.desktop,
               MessageManager.formatMessage(
                       "label.colour_scheme_exists_overwrite", new Object[] {
-                          schemeName.getText(), schemeName.getText() }),
+                          name, name }),
               MessageManager.getString("label.duplicate_scheme_name"),
               JvOptionPane.YES_NO_OPTION);
       if (reply != JvOptionPane.YES_OPTION)
       {
         return;
       }
-
-      userColourSchemes.remove(schemeName.getText());
+      ColourSchemes.getInstance().removeColourScheme(name);
     }
     JalviewFileChooser chooser = new JalviewFileChooser("jc",
             "Jalview User Colours");
 
-    chooser.setFileView(new JalviewFileView());
+    JalviewFileView fileView = new JalviewFileView();
+    chooser.setFileView(fileView);
     chooser.setDialogTitle(MessageManager
             .getString("label.save_colour_scheme"));
     chooser.setToolTipText(MessageManager.getString("action.save"));
@@ -842,205 +734,150 @@ public class UserDefinedColours extends GUserDefinedColours implements
 
     if (value == JalviewFileChooser.APPROVE_OPTION)
     {
-      String choice = chooser.getSelectedFile().getPath();
-      String defaultColours = jalview.bin.Cache.getDefault(
-              "USER_DEFINED_COLOURS", choice);
-      if (defaultColours.indexOf(choice) == -1)
-      {
-        if (defaultColours.length() > 0)
-        {
-          defaultColours = defaultColours.concat("|");
-        }
-        defaultColours = defaultColours.concat(choice);
-      }
-
-      userColourSchemes.put(schemeName.getText(), getSchemeFromButtons());
-
-      ap.alignFrame.updateUserColourMenu();
-
-      jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS", defaultColours);
-
-      jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
-
-      ucs.setSchemeName(schemeName.getText());
-      try
-      {
-        PrintWriter out = new PrintWriter(new OutputStreamWriter(
-                new FileOutputStream(choice), "UTF-8"));
-
-        for (int i = 0; i < buttonPanel.getComponentCount(); i++)
-        {
-          JButton button = (JButton) buttonPanel.getComponent(i);
-          jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
-          col.setName(button.getText());
-          col.setRGB(jalview.util.Format.getHexString(button
-                  .getBackground()));
-          ucs.addColour(col);
-        }
-
-        ucs.marshal(out);
-        out.close();
-      } catch (Exception ex)
-      {
-        ex.printStackTrace();
-      }
+      File file = chooser.getSelectedFile();
+      addNewColourScheme(file.getPath());
+      saveToFile(file);
     }
   }
 
   /**
-   * DOCUMENT ME!
+   * Adds the current colour scheme to the Jalview properties file so it is
+   * loaded on next startup, and updates the Colour menu in the parent
+   * AlignFrame (if there is one). Note this action does not including applying
+   * the colour scheme.
    * 
-   * @param e
-   *          DOCUMENT ME!
+   * @param filePath
    */
-  @Override
-  protected void cancelButton_actionPerformed(ActionEvent e)
+  protected void addNewColourScheme(String filePath)
   {
-    if (ap != null)
+    /*
+     * update the delimited list of user defined colour files in
+     * Jalview property USER_DEFINED_COLOURS
+     */
+    String defaultColours = Cache
+            .getDefault(USER_DEFINED_COLOURS, filePath);
+    if (defaultColours.indexOf(filePath) == -1)
     {
-      if (seqGroup != null)
-      {
-        seqGroup.cs = oldColourScheme;
-      }
-      else if (ap != null)
+      if (defaultColours.length() > 0)
       {
-        ap.av.setGlobalColourScheme(oldColourScheme);
+        defaultColours = defaultColours.concat("|");
       }
-      ap.paintAlignment(true);
+      defaultColours = defaultColours.concat(filePath);
     }
+    Cache.setProperty(USER_DEFINED_COLOURS, defaultColours);
 
-    if (jmol != null)
-    {
-      jmol.setJalviewColourScheme(oldColourScheme);
-    }
+    /*
+     * construct and register the colour scheme
+     */
+    UserColourScheme ucs = getSchemeFromButtons();
+    ColourSchemes.getInstance().registerColourScheme(ucs);
 
-    try
-    {
-      frame.setClosed(true);
-    } catch (Exception ex)
+    /*
+     * update the Colour menu items
+     */
+    if (ap != null)
     {
+      ap.alignFrame.buildColourMenu();
     }
   }
 
-  static Hashtable userColourSchemes;
-
-  public static Hashtable getUserColourSchemes()
-  {
-    return userColourSchemes;
-  }
-
-  public static void initUserColourSchemes(String files)
+  /**
+   * Saves the colour scheme to file in XML format
+   * 
+   * @param path
+   */
+  protected void saveToFile(File toFile)
   {
-    userColourSchemes = new Hashtable();
-
-    if (files == null || files.length() == 0)
+    /*
+     * build a Java model of colour scheme as XML, and 
+     * marshal to file
+     */
+    JalviewUserColours ucs = new JalviewUserColours();
+    ucs.setSchemeName(schemeName.getText());
+    try
     {
-      return;
-    }
+      PrintWriter out = new PrintWriter(new OutputStreamWriter(
+              new FileOutputStream(toFile), "UTF-8"));
 
-    // In case colours can't be loaded, we'll remove them
-    // from the default list here.
-    StringBuffer coloursFound = new StringBuffer();
-    StringTokenizer st = new StringTokenizer(files, "|");
-    while (st.hasMoreElements())
-    {
-      String file = st.nextToken();
-      try
-      {
-        UserColourScheme ucs = loadColours(file);
-        if (ucs != null)
-        {
-          if (coloursFound.length() > 0)
-          {
-            coloursFound.append("|");
-          }
-          coloursFound.append(file);
-          userColourSchemes.put(ucs.getName(), ucs);
-        }
-      } catch (Exception ex)
+      for (int i = 0; i < buttonPanel.getComponentCount(); i++)
       {
-        System.out.println("Error loading User ColourFile\n" + ex);
+        JButton button = (JButton) buttonPanel.getComponent(i);
+        Colour col = new Colour();
+        col.setName(button.getText());
+        col.setRGB(Format.getHexString(button.getBackground()));
+        ucs.addColour(col);
       }
-    }
-    if (!files.equals(coloursFound.toString()))
+      ucs.marshal(out);
+      out.close();
+    } catch (Exception ex)
     {
-      if (coloursFound.toString().length() > 1)
-      {
-        jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS",
-                coloursFound.toString());
-      }
-      else
-      {
-        jalview.bin.Cache.applicationProperties
-                .remove("USER_DEFINED_COLOURS");
-      }
+      ex.printStackTrace();
     }
   }
 
-  public static void removeColourFromDefaults(String target)
+  /**
+   * On cancel, restores the colour scheme before the dialogue was opened
+   * 
+   * @param e
+   */
+  @Override
+  protected void cancelButton_actionPerformed(ActionEvent e)
   {
-    // The only way to find colours by name is to load them in
-    // In case colours can't be loaded, we'll remove them
-    // from the default list here.
-
-    userColourSchemes = new Hashtable();
-
-    StringBuffer coloursFound = new StringBuffer();
-    StringTokenizer st = new StringTokenizer(
-            jalview.bin.Cache.getProperty("USER_DEFINED_COLOURS"), "|");
-
-    while (st.hasMoreElements())
+    if (ap != null)
     {
-      String file = st.nextToken();
-      try
+      if (seqGroup != null)
       {
-        UserColourScheme ucs = loadColours(file);
-        if (ucs != null && !ucs.getName().equals(target))
-        {
-          if (coloursFound.length() > 0)
-          {
-            coloursFound.append("|");
-          }
-          coloursFound.append(file);
-          userColourSchemes.put(ucs.getName(), ucs);
-        }
-      } catch (Exception ex)
+        seqGroup.setColourScheme(oldColourScheme);
+      }
+      else
       {
-        System.out.println("Error loading User ColourFile\n" + ex);
+        ap.alignFrame.changeColour(oldColourScheme);
       }
+      ap.paintAlignment(true);
     }
 
-    if (coloursFound.toString().length() > 1)
+    if (structureViewer != null)
     {
-      jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS",
-              coloursFound.toString());
+      structureViewer.setJalviewColourScheme(oldColourScheme);
     }
-    else
+
+    try
+    {
+      frame.setClosed(true);
+    } catch (Exception ex)
     {
-      jalview.bin.Cache.applicationProperties
-              .remove("USER_DEFINED_COLOURS");
     }
-
   }
 
   @Override
   public void caseSensitive_actionPerformed(ActionEvent e)
   {
-    resetButtonPanel(caseSensitive.isSelected());
-    lcaseColour.setEnabled(caseSensitive.isSelected());
+    boolean selected = caseSensitive.isSelected();
+    resetButtonPanel(selected);
+    lcaseColour.setEnabled(selected);
+    lcaseColour.setForeground(Color.GRAY);
   }
 
+  /**
+   * Action on clicking 'Lower case colour', which results in changing colour of
+   * all lower-case buttons when a colour is picked. A second click of the
+   * button turns off this behaviour.
+   */
   @Override
   public void lcaseColour_actionPerformed(ActionEvent e)
   {
-    if (selectedButtons == null)
+    boolean enable = !selectedButtons.contains(lcaseColour);
+    selectedButtons.clear();
+    if (enable)
     {
-      selectedButtons = new ArrayList<JButton>();
+      selectedButtons.add(lcaseColour);
+      lcaseColour.setForeground(lowerCaseButtons.get(0).getForeground());
+      lcaseColour.setForeground(Color.black);
     }
     else
     {
-      selectedButtons.clear();
+      lcaseColour.setBackground(Color.white);
+      lcaseColour.setForeground(Color.gray);
     }
-    selectedButtons.add(lcaseColour);
   }
 }
index 82e71b5..9a4071d 100755 (executable)
@@ -32,8 +32,9 @@ import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemeProperty;
-import jalview.schemes.UserColourScheme;
+import jalview.util.ColorUtils;
 
+import java.awt.Color;
 import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.InputStreamReader;
@@ -581,7 +582,7 @@ public class AnnotationFile
       if (sg.cs != null)
       {
         text.append("colour=");
-        text.append(ColourSchemeProperty.getColourName(sg.cs));
+        text.append(sg.cs.toString());
         text.append("\t");
         if (sg.cs.getThreshold() != 0)
         {
@@ -1223,29 +1224,21 @@ public class AnnotationFile
 
   Annotation parseAnnotation(String string, int graphStyle)
   {
-    boolean hasSymbols = (graphStyle == AlignmentAnnotation.NO_GRAPH); // don't
-    // do the
-    // glyph
-    // test
-    // if we
-    // don't
-    // want
-    // secondary
-    // structure
+    // don't do the glyph test if we don't want secondary structure
+    boolean hasSymbols = (graphStyle == AlignmentAnnotation.NO_GRAPH);
     String desc = null, displayChar = null;
     char ss = ' '; // secondaryStructure
     float value = 0;
     boolean parsedValue = false, dcset = false;
 
     // find colour here
-    java.awt.Color colour = null;
+    Color colour = null;
     int i = string.indexOf("[");
     int j = string.indexOf("]");
     if (i > -1 && j > -1)
     {
-      UserColourScheme ucs = new UserColourScheme();
-
-      colour = ucs.getColourFromString(string.substring(i + 1, j));
+      colour = ColorUtils.parseColourString(string.substring(i + 1,
+              j));
       if (i > 0 && string.charAt(i - 1) == ',')
       {
         // clip the preceding comma as well
@@ -1347,7 +1340,7 @@ public class AnnotationFile
 
   void colourAnnotations(AlignmentI al, String label, String colour)
   {
-    UserColourScheme ucs = new UserColourScheme(colour);
+    Color awtColour = ColorUtils.parseColourString(colour);
     Annotation[] annotations;
     for (int i = 0; i < al.getAlignmentAnnotation().length; i++)
     {
@@ -1358,7 +1351,7 @@ public class AnnotationFile
         {
           if (annotations[j] != null)
           {
-            annotations[j].colour = ucs.findColour('A');
+            annotations[j].colour = awtColour;
           }
         }
       }
@@ -1428,15 +1421,22 @@ public class AnnotationFile
           SequenceGroup groupRef)
   {
     String group = st.nextToken();
-    AlignmentAnnotation annotation = null, alannot[] = al
-            .getAlignmentAnnotation();
-    float value = new Float(st.nextToken()).floatValue();
+    AlignmentAnnotation[] alannot = al.getAlignmentAnnotation();
+    String nextToken = st.nextToken();
+    float value = 0f;
+    try
+    {
+      value = Float.valueOf(nextToken);
+    } catch (NumberFormatException e)
+    {
+      System.err.println("line " + nlinesread + ": Threshold '" + nextToken
+              + "' invalid, setting to zero");
+    }
     String label = st.hasMoreTokens() ? st.nextToken() : null;
-    java.awt.Color colour = null;
+    Color colour = null;
     if (st.hasMoreTokens())
     {
-      UserColourScheme ucs = new UserColourScheme(st.nextToken());
-      colour = ucs.findColour('A');
+      colour = ColorUtils.parseColourString(st.nextToken());
     }
     if (alannot != null)
     {
@@ -1450,10 +1450,6 @@ public class AnnotationFile
         }
       }
     }
-    if (annotation == null)
-    {
-      return;
-    }
   }
 
   void addGroup(AlignmentI al, StringTokenizer st)
@@ -1613,8 +1609,7 @@ public class AnnotationFile
     if (sg != null)
     {
       String keyValue, key, value;
-      ColourSchemeI def = sg.cs;
-      sg.cs = null;
+      ColourSchemeI def = sg.getColourScheme();
       while (st.hasMoreTokens())
       {
         keyValue = st.nextToken();
@@ -1627,7 +1622,8 @@ public class AnnotationFile
         }
         else if (key.equalsIgnoreCase("colour"))
         {
-          sg.cs = ColourSchemeProperty.getColour(al, value);
+          sg.cs.setColourScheme(ColourSchemeProperty
+                  .getColourScheme(al, value));
         }
         else if (key.equalsIgnoreCase("pidThreshold"))
         {
@@ -1648,7 +1644,7 @@ public class AnnotationFile
         }
         else if (key.equalsIgnoreCase("outlineColour"))
         {
-          sg.setOutlineColour(new UserColourScheme(value).findColour('A'));
+          sg.setOutlineColour(ColorUtils.parseColourString(value));
         }
         else if (key.equalsIgnoreCase("displayBoxes"))
         {
@@ -1668,11 +1664,11 @@ public class AnnotationFile
         }
         else if (key.equalsIgnoreCase("textCol1"))
         {
-          sg.textColour = new UserColourScheme(value).findColour('A');
+          sg.textColour = ColorUtils.parseColourString(value);
         }
         else if (key.equalsIgnoreCase("textCol2"))
         {
-          sg.textColour2 = new UserColourScheme(value).findColour('A');
+          sg.textColour2 = ColorUtils.parseColourString(value);
         }
         else if (key.equalsIgnoreCase("textColThreshold"))
         {
@@ -1680,9 +1676,8 @@ public class AnnotationFile
         }
         else if (key.equalsIgnoreCase("idColour"))
         {
-          // consider warning if colour doesn't resolve to a real colour
-          sg.setIdColour((def = new UserColourScheme(value))
-                  .findColour('A'));
+          Color idColour = ColorUtils.parseColourString(value);
+          sg.setIdColour(idColour == null ? Color.black : idColour);
         }
         else if (key.equalsIgnoreCase("hide"))
         {
@@ -1696,9 +1691,9 @@ public class AnnotationFile
         }
         sg.recalcConservation();
       }
-      if (sg.cs == null)
+      if (sg.getColourScheme() == null)
       {
-        sg.cs = def;
+        sg.setColourScheme(def);
       }
     }
   }
index 6af0cdf..48eeee3 100755 (executable)
@@ -35,11 +35,12 @@ import jalview.io.gff.GffHelperBase;
 import jalview.io.gff.GffHelperFactory;
 import jalview.io.gff.GffHelperI;
 import jalview.schemes.FeatureColour;
-import jalview.schemes.UserColourScheme;
+import jalview.util.ColorUtils;
 import jalview.util.MapList;
 import jalview.util.ParseHtmlBodyAndLinks;
 import jalview.util.StringUtils;
 
+import java.awt.Color;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -355,8 +356,8 @@ public class FeaturesFile extends AlignFile implements FeaturesSourceI
        * Perhaps an old style groups file with no colours -
        * synthesize a colour from the feature type
        */
-      UserColourScheme ucs = new UserColourScheme(ft);
-      featureColours.put(ft, new FeatureColour(ucs.findColour('A')));
+      Color colour = ColorUtils.createColourFromName(ft);
+      featureColours.put(ft, new FeatureColour(colour));
     }
     SequenceFeature sf = new SequenceFeature(ft, desc, "", startPos,
             endPos, featureGroup);
index 7a12076..27ebe5a 100644 (file)
@@ -46,8 +46,9 @@ import jalview.json.binding.biojson.v1.ColourSchemeMapper;
 import jalview.json.binding.biojson.v1.SequenceFeaturesPojo;
 import jalview.json.binding.biojson.v1.SequenceGrpPojo;
 import jalview.json.binding.biojson.v1.SequencePojo;
-import jalview.schemes.ColourSchemeProperty;
-import jalview.schemes.UserColourScheme;
+import jalview.schemes.JalviewColourScheme;
+import jalview.schemes.ResidueColourScheme;
+import jalview.util.ColorUtils;
 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
 
 import java.awt.Color;
@@ -215,10 +216,13 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
       {
         // These color schemes require annotation, disable them if annotations
         // are not exported
-        if (globalColourScheme.equalsIgnoreCase("RNA Helices")
-                || globalColourScheme.equalsIgnoreCase("T-COFFEE SCORES"))
+        if (globalColourScheme
+                .equalsIgnoreCase(JalviewColourScheme.RNAHelices.toString())
+                || globalColourScheme
+                        .equalsIgnoreCase(JalviewColourScheme.TCoffee
+                                .toString()))
         {
-          jsonAlignmentPojo.setGlobalColorScheme("None");
+          jsonAlignmentPojo.setGlobalColorScheme(ResidueColourScheme.NONE);
         }
       }
 
@@ -235,8 +239,8 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
         {
           SequenceGrpPojo seqGrpPojo = new SequenceGrpPojo();
           seqGrpPojo.setGroupName(seqGrp.getName());
-          seqGrpPojo.setColourScheme(ColourSchemeProperty
-                  .getColourName(seqGrp.cs));
+          seqGrpPojo.setColourScheme(seqGrp.getColourScheme()
+                  .getSchemeName());
           seqGrpPojo.setColourText(seqGrp.getColourText());
           seqGrpPojo.setDescription(seqGrp.getDescription());
           seqGrpPojo.setDisplayBoxes(seqGrp.getDisplayBoxes());
@@ -524,8 +528,8 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
         }
         SequenceGroup seqGrp = new SequenceGroup(grpSeqs, grpName, null,
                 displayBoxes, displayText, colourText, startRes, endRes);
-        seqGrp.cs = ColourSchemeMapper.getJalviewColourScheme(colourScheme,
-                seqGrp);
+        seqGrp.setColourScheme(ColourSchemeMapper.getJalviewColourScheme(
+                colourScheme, seqGrp));
         seqGrp.setShowNonconserved(showNonconserved);
         seqGrp.setDescription(description);
         this.seqGroups.add(seqGrp);
@@ -563,7 +567,7 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
             annotations[count] = new Annotation(displayChar, desc, ss, val);
             if (annot.get("colour") != null)
             {
-              Color color = UserColourScheme.getColourFromString(annot.get(
+              Color color = ColorUtils.parseColourString(annot.get(
                       "colour").toString());
               annotations[count].colour = color;
             }
@@ -760,8 +764,7 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
         }
       }
     }
-    globalColourScheme = ColourSchemeProperty.getColourName(viewport
-            .getGlobalColourScheme());
+    globalColourScheme = viewport.getGlobalColourScheme().getSchemeName();
     setDisplayedFeatures(viewport.getFeaturesDisplayed());
     showSeqFeatures = viewport.isShowSequenceFeatures();
 
index c3ec951..648954f 100644 (file)
@@ -37,10 +37,10 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 /**
- * A file parse for T-Coffee score ascii format. This file contains the
- * alignment consensus for each resude in any sequence.
+ * A file parser for T-Coffee score ascii format. This file contains the
+ * alignment consensus for each residue in any sequence.
  * <p>
- * This file is procuded by <code>t_coffee</code> providing the option
+ * This file is produced by <code>t_coffee</code> providing the option
  * <code>-output=score_ascii </code> to the program command line
  * 
  * An example file is the following
@@ -91,17 +91,26 @@ import java.util.regex.Pattern;
  */
 public class TCoffeeScoreFile extends AlignFile
 {
-  public TCoffeeScoreFile(String inFile, DataSourceType fileSourceType)
-          throws IOException
-  {
-    super(inFile, fileSourceType);
 
-  }
+  /**
+   * TCOFFEE score colourscheme
+   */
+  static final Color[] colors = { new Color(102, 102, 255), // 0: lilac #6666FF
+      new Color(0, 255, 0), // 1: green #00FF00
+      new Color(102, 255, 0), // 2: lime green #66FF00
+      new Color(204, 255, 0), // 3: greeny yellow #CCFF00
+      new Color(255, 255, 0), // 4: yellow #FFFF00
+      new Color(255, 204, 0), // 5: orange #FFCC00
+      new Color(255, 153, 0), // 6: deep orange #FF9900
+      new Color(255, 102, 0), // 7: ochre #FF6600
+      new Color(255, 51, 0), // 8: red #FF3300
+      new Color(255, 34, 0) // 9: redder #FF2000
+  };
 
-  public TCoffeeScoreFile(FileParse source) throws IOException
-  {
-    super(source);
-  }
+  public final static String TCOFFEE_SCORE = "TCoffeeScore";
+
+  static Pattern SCORES_WITH_RESIDUE_NUMS = Pattern
+          .compile("^\\d+\\s([^\\s]+)\\s+\\d+$");
 
   /** The {@link Header} structure holder */
   Header header;
@@ -114,6 +123,18 @@ public class TCoffeeScoreFile extends AlignFile
 
   Integer fWidth;
 
+  public TCoffeeScoreFile(String inFile, DataSourceType fileSourceType)
+          throws IOException
+  {
+    super(inFile, fileSourceType);
+
+  }
+
+  public TCoffeeScoreFile(FileParse source) throws IOException
+  {
+    super(source);
+  }
+
   /**
    * Parse the provided reader for the T-Coffee scores file format
    * 
@@ -399,9 +420,6 @@ public class TCoffeeScoreFile extends AlignFile
     }
   }
 
-  static Pattern SCORES_WITH_RESIDUE_NUMS = Pattern
-          .compile("^\\d+\\s([^\\s]+)\\s+\\d+$");
-
   /**
    * Read a scores block ihe provided stream.
    * 
@@ -525,23 +543,6 @@ public class TCoffeeScoreFile extends AlignFile
   }
 
   /**
-   * TCOFFEE score colourscheme
-   */
-  static final Color[] colors = { new Color(102, 102, 255), // #6666FF
-      new Color(0, 255, 0), // #00FF00
-      new Color(102, 255, 0), // #66FF00
-      new Color(204, 255, 0), // #CCFF00
-      new Color(255, 255, 0), // #FFFF00
-      new Color(255, 204, 0), // #FFCC00
-      new Color(255, 153, 0), // #FF9900
-      new Color(255, 102, 0), // #FF6600
-      new Color(255, 51, 0), // #FF3300
-      new Color(255, 34, 0) // #FF2000
-  };
-
-  public final static String TCOFFEE_SCORE = "TCoffeeScore";
-
-  /**
    * generate annotation for this TCoffee score set on the given alignment
    * 
    * @param al
index 6530d3d..b39f4a8 100755 (executable)
@@ -23,12 +23,11 @@ package jalview.jbgui;
 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
 import jalview.api.SplitContainerI;
 import jalview.bin.Cache;
-import jalview.gui.JvOptionPane;
 import jalview.gui.JvSwingUtils;
 import jalview.gui.Preferences;
 import jalview.io.FileFormats;
-import jalview.schemes.ColourSchemeProperty;
 import jalview.util.MessageManager;
+import jalview.util.Platform;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
@@ -66,15 +65,13 @@ public class GAlignFrame extends JInternalFrame
 
   protected JMenuItem closeMenuItem = new JMenuItem();
 
-  protected JMenu colourMenu = new JMenu();
-
   protected JMenu webService = new JMenu();
 
   protected JMenuItem webServiceNoServices;
 
-  public JCheckBoxMenuItem viewBoxesMenuItem = new JCheckBoxMenuItem();
+  protected JCheckBoxMenuItem viewBoxesMenuItem = new JCheckBoxMenuItem();
 
-  public JCheckBoxMenuItem viewTextMenuItem = new JCheckBoxMenuItem();
+  protected JCheckBoxMenuItem viewTextMenuItem = new JCheckBoxMenuItem();
 
   protected JMenu sortByAnnotScore = new JMenu();
 
@@ -82,58 +79,19 @@ public class GAlignFrame extends JInternalFrame
 
   protected JMenu outputTextboxMenu = new JMenu();
 
-  protected JRadioButtonMenuItem clustalColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem zappoColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem taylorColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem hydrophobicityColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem helixColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem strandColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem turnColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem buriedColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem PIDColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem BLOSUM62Colour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem nucleotideColour = new JRadioButtonMenuItem();
+  protected JCheckBoxMenuItem annotationPanelMenuItem = new JCheckBoxMenuItem();
 
-  protected JRadioButtonMenuItem purinePyrimidineColour = new JRadioButtonMenuItem();
+  protected JCheckBoxMenuItem colourTextMenuItem = new JCheckBoxMenuItem();
 
-  protected JRadioButtonMenuItem RNAInteractionColour = new JRadioButtonMenuItem();
-
-  // protected JRadioButtonMenuItem covariationColour = new
-  // JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem tcoffeeColour = new JRadioButtonMenuItem();
-
-  public JCheckBoxMenuItem annotationPanelMenuItem = new JCheckBoxMenuItem();
-
-  public JCheckBoxMenuItem colourTextMenuItem = new JCheckBoxMenuItem();
-
-  public JCheckBoxMenuItem showNonconservedMenuItem = new JCheckBoxMenuItem();
+  protected JCheckBoxMenuItem showNonconservedMenuItem = new JCheckBoxMenuItem();
 
   protected JMenuItem undoMenuItem = new JMenuItem();
 
   protected JMenuItem redoMenuItem = new JMenuItem();
 
-  public JCheckBoxMenuItem conservationMenuItem = new JCheckBoxMenuItem();
-
-  JRadioButtonMenuItem noColourmenuItem = new JRadioButtonMenuItem();
-
-  public JCheckBoxMenuItem wrapMenuItem = new JCheckBoxMenuItem();
+  protected JCheckBoxMenuItem wrapMenuItem = new JCheckBoxMenuItem();
 
-  public JCheckBoxMenuItem renderGapsMenuItem = new JCheckBoxMenuItem();
-
-  public JCheckBoxMenuItem abovePIDThreshold = new JCheckBoxMenuItem();
+  protected JCheckBoxMenuItem renderGapsMenuItem = new JCheckBoxMenuItem();
 
   public JCheckBoxMenuItem showSeqFeatures = new JCheckBoxMenuItem();
 
@@ -143,19 +101,29 @@ public class GAlignFrame extends JInternalFrame
 
   JMenu pasteMenu = new JMenu();
 
-  public JCheckBoxMenuItem applyToAllGroups = new JCheckBoxMenuItem();
+  protected JCheckBoxMenuItem seqLimits = new JCheckBoxMenuItem();
+
+  protected JCheckBoxMenuItem scaleAbove = new JCheckBoxMenuItem();
+
+  protected JCheckBoxMenuItem scaleLeft = new JCheckBoxMenuItem();
+
+  protected JCheckBoxMenuItem scaleRight = new JCheckBoxMenuItem();
+
+  protected JCheckBoxMenuItem applyToAllGroups;
+
+  protected JMenu colourMenu = new JMenu();
 
-  public JCheckBoxMenuItem seqLimits = new JCheckBoxMenuItem();
+  protected JRadioButtonMenuItem textColour;
 
-  public JCheckBoxMenuItem scaleAbove = new JCheckBoxMenuItem();
+  protected JCheckBoxMenuItem conservationMenuItem;
 
-  public JCheckBoxMenuItem scaleLeft = new JCheckBoxMenuItem();
+  protected JMenuItem modifyConservation;
 
-  public JCheckBoxMenuItem scaleRight = new JCheckBoxMenuItem();
+  protected JCheckBoxMenuItem abovePIDThreshold;
 
-  protected JMenuItem modifyConservation = new JMenuItem();
+  protected JMenuItem modifyPID;
 
-  protected JMenuItem modifyPID = new JMenuItem();
+  protected JMenuItem annotationColour;
 
   protected JMenu sortByTreeMenu = new JMenu();
 
@@ -169,8 +137,6 @@ public class GAlignFrame extends JInternalFrame
 
   protected JCheckBoxMenuItem showDbRefsMenuitem = new JCheckBoxMenuItem();
 
-  protected ButtonGroup colours = new ButtonGroup();
-
   protected JMenuItem showTranslation = new JMenuItem();
 
   protected JMenuItem showReverse = new JMenuItem();
@@ -181,8 +147,6 @@ public class GAlignFrame extends JInternalFrame
 
   protected JMenuItem runGroovy = new JMenuItem();
 
-  protected JMenuItem rnahelicesColour = new JMenuItem();
-
   protected JCheckBoxMenuItem autoCalculate = new JCheckBoxMenuItem();
 
   protected JCheckBoxMenuItem sortByTree = new JCheckBoxMenuItem();
@@ -267,7 +231,7 @@ public class GAlignFrame extends JInternalFrame
       System.err.println(e.toString());
     }
 
-    if (!jalview.util.Platform.isAMac())
+    if (!Platform.isAMac())
     {
       closeMenuItem.setMnemonic('C');
       outputTextboxMenu.setMnemonic('T');
@@ -278,201 +242,12 @@ public class GAlignFrame extends JInternalFrame
       pasteMenu.setMnemonic('P');
       reload.setMnemonic('R');
     }
-
-    if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
-    {
-      java.util.Enumeration userColours = jalview.gui.UserDefinedColours
-              .getUserColourSchemes().keys();
-
-      while (userColours.hasMoreElements())
-      {
-        final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(
-                userColours.nextElement().toString());
-        radioItem.setName("USER_DEFINED");
-        radioItem.addMouseListener(new MouseAdapter()
-        {
-          @Override
-          public void mousePressed(MouseEvent evt)
-          {
-            if (evt.isPopupTrigger()) // Mac
-            {
-              offerRemoval(radioItem);
-            }
-          }
-
-          @Override
-          public void mouseReleased(MouseEvent evt)
-          {
-            if (evt.isPopupTrigger()) // Windows
-            {
-              offerRemoval(radioItem);
-            }
-          }
-
-          /**
-           * @param radioItem
-           */
-          void offerRemoval(final JRadioButtonMenuItem radioItem)
-          {
-            radioItem.removeActionListener(radioItem.getActionListeners()[0]);
-
-            int option = JvOptionPane.showInternalConfirmDialog(
-                    jalview.gui.Desktop.desktop, MessageManager
-                            .getString("label.remove_from_default_list"),
-                    MessageManager
-                            .getString("label.remove_user_defined_colour"),
-                    JvOptionPane.YES_NO_OPTION);
-            if (option == JvOptionPane.YES_OPTION)
-            {
-              jalview.gui.UserDefinedColours
-                      .removeColourFromDefaults(radioItem.getText());
-              colourMenu.remove(radioItem);
-            }
-            else
-            {
-              radioItem.addActionListener(new ActionListener()
-              {
-                @Override
-                public void actionPerformed(ActionEvent evt)
-                {
-                  userDefinedColour_actionPerformed(evt);
-                }
-              });
-            }
-          }
-        });
-        radioItem.addActionListener(new ActionListener()
-        {
-          @Override
-          public void actionPerformed(ActionEvent evt)
-          {
-            userDefinedColour_actionPerformed(evt);
-          }
-        });
-        colourMenu.insert(radioItem, 15);
-        colours.add(radioItem);
-      }
-    }
-    colours.add(noColourmenuItem);
-    colours.add(clustalColour);
-    colours.add(zappoColour);
-    colours.add(taylorColour);
-    colours.add(hydrophobicityColour);
-    colours.add(helixColour);
-    colours.add(strandColour);
-    colours.add(turnColour);
-    colours.add(buriedColour);
-    colours.add(userDefinedColour);
-    colours.add(PIDColour);
-    colours.add(BLOSUM62Colour);
-    colours.add(nucleotideColour);
-    colours.add(purinePyrimidineColour);
-    // colours.add(covariationColour);
-    colours.add(tcoffeeColour);
-    colours.add(RNAInteractionColour);
-    setColourSelected(jalview.bin.Cache.getDefault(
-            Preferences.DEFAULT_COLOUR, "None"));
-  }
-
-  public void setColourSelected(String defaultColour)
-  {
-
-    if (defaultColour != null)
-    {
-      int index = ColourSchemeProperty
-              .getColourIndexFromName(defaultColour);
-
-      switch (index)
-      {
-      case ColourSchemeProperty.CLUSTAL:
-        clustalColour.setSelected(true);
-
-        break;
-
-      case ColourSchemeProperty.BLOSUM:
-        BLOSUM62Colour.setSelected(true);
-
-        break;
-
-      case ColourSchemeProperty.PID:
-        PIDColour.setSelected(true);
-
-        break;
-
-      case ColourSchemeProperty.ZAPPO:
-        zappoColour.setSelected(true);
-
-        break;
-
-      case ColourSchemeProperty.TAYLOR:
-        taylorColour.setSelected(true);
-        break;
-
-      case ColourSchemeProperty.HYDROPHOBIC:
-        hydrophobicityColour.setSelected(true);
-
-        break;
-
-      case ColourSchemeProperty.HELIX:
-        helixColour.setSelected(true);
-
-        break;
-
-      case ColourSchemeProperty.STRAND:
-        strandColour.setSelected(true);
-
-        break;
-
-      case ColourSchemeProperty.TURN:
-        turnColour.setSelected(true);
-
-        break;
-
-      case ColourSchemeProperty.BURIED:
-        buriedColour.setSelected(true);
-
-        break;
-
-      case ColourSchemeProperty.NUCLEOTIDE:
-        nucleotideColour.setSelected(true);
-
-        break;
-
-      case ColourSchemeProperty.TCOFFEE:
-        tcoffeeColour.setSelected(true);
-        break;
-
-      case ColourSchemeProperty.PURINEPYRIMIDINE:
-        purinePyrimidineColour.setSelected(true);
-
-        break;
-
-      case ColourSchemeProperty.RNAINTERACTION:
-        RNAInteractionColour.setSelected(true);
-
-        break;
-      /*
-       * case ColourSchemeProperty.COVARIATION:
-       * covariationColour.setSelected(true);
-       * 
-       * break;
-       */
-      case ColourSchemeProperty.USER_DEFINED:
-        userDefinedColour.setSelected(true);
-
-        break;
-      case ColourSchemeProperty.NONE:
-      default:
-        noColourmenuItem.setSelected(true);
-        break;
-
-      }
-    }
-
   }
 
   private void jbInit() throws Exception
   {
+    initColourMenu();
+
     JMenuItem saveAs = new JMenuItem(
             MessageManager.getString("action.save_as"));
     ActionListener al = new ActionListener()
@@ -483,6 +258,8 @@ public class GAlignFrame extends JInternalFrame
         saveAs_actionPerformed(e);
       }
     };
+
+    // FIXME getDefaultToolkit throws an exception in Headless mode
     KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S, Toolkit
             .getDefaultToolkit().getMenuShortcutKeyMask()
             | KeyEvent.SHIFT_MASK, false);
@@ -671,7 +448,7 @@ public class GAlignFrame extends JInternalFrame
       }
     });
     showNonconservedMenuItem.setText(MessageManager
-            .getString("label.show_non_conversed"));
+            .getString("label.show_non_conserved"));
     showNonconservedMenuItem.setState(false);
     showNonconservedMenuItem.addActionListener(new ActionListener()
     {
@@ -785,149 +562,10 @@ public class GAlignFrame extends JInternalFrame
     statusBar.setText(MessageManager.getString("label.status_bar"));
     outputTextboxMenu.setText(MessageManager
             .getString("label.out_to_textbox"));
-    clustalColour.setText(MessageManager.getString("label.clustalx"));
-    clustalColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        clustalColour_actionPerformed(e);
-      }
-    });
-    zappoColour.setText(MessageManager.getString("label.zappo"));
-    zappoColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        zappoColour_actionPerformed(e);
-      }
-    });
-    taylorColour.setText(MessageManager.getString("label.taylor"));
-    taylorColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        taylorColour_actionPerformed(e);
-      }
-    });
-    hydrophobicityColour.setText(MessageManager
-            .getString("label.hydrophobicity"));
-    hydrophobicityColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        hydrophobicityColour_actionPerformed(e);
-      }
-    });
-    helixColour.setText(MessageManager.getString("label.helix_propensity"));
-    helixColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        helixColour_actionPerformed(e);
-      }
-    });
-    strandColour.setText(MessageManager
-            .getString("label.strand_propensity"));
-    strandColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        strandColour_actionPerformed(e);
-      }
-    });
-    turnColour.setText(MessageManager.getString("label.turn_propensity"));
-    turnColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        turnColour_actionPerformed(e);
-      }
-    });
-    buriedColour.setText(MessageManager.getString("label.buried_index"));
-    buriedColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        buriedColour_actionPerformed(e);
-      }
-    });
-    userDefinedColour.setText(MessageManager
-            .getString("action.user_defined"));
-    userDefinedColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        userDefinedColour_actionPerformed(e);
-      }
-    });
-    PIDColour
-            .setText(MessageManager.getString("label.percentage_identity"));
-    PIDColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        PIDColour_actionPerformed(e);
-      }
-    });
-    BLOSUM62Colour
-            .setText(MessageManager.getString("label.blosum62_score"));
-    BLOSUM62Colour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        BLOSUM62Colour_actionPerformed(e);
-      }
-    });
-    nucleotideColour.setText(MessageManager.getString("label.nucleotide"));
-    nucleotideColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        nucleotideColour_actionPerformed(e);
-      }
-    });
-
-    purinePyrimidineColour.setText(MessageManager
-            .getString("label.purine_pyrimidine"));
-    purinePyrimidineColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        purinePyrimidineColour_actionPerformed(e);
-      }
-    });
 
-    RNAInteractionColour.setText("RNA Interaction type");
-    RNAInteractionColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        RNAInteractionColour_actionPerformed(e);
-      }
-    });
-    /*
-     * covariationColour.setText("Covariation");
-     * covariationColour.addActionListener(new ActionListener() { public void
-     * actionPerformed(ActionEvent e) { covariationColour_actionPerformed(e); }
-     * });
-     */
 
     JMenuItem avDistanceTreeBlosumMenuItem = new JMenuItem(
-            MessageManager.getString("label.average_distance_bloslum62"));
+            MessageManager.getString("label.average_distance_blosum62"));
     avDistanceTreeBlosumMenuItem.addActionListener(new ActionListener()
     {
       @Override
@@ -1041,7 +679,8 @@ public class GAlignFrame extends JInternalFrame
         sortAnnotations_actionPerformed();
       }
     });
-    colourTextMenuItem.setText(MessageManager
+    colourTextMenuItem = new JCheckBoxMenuItem(
+            MessageManager
             .getString("label.colour_text"));
     colourTextMenuItem.addActionListener(new ActionListener()
     {
@@ -1113,25 +752,6 @@ public class GAlignFrame extends JInternalFrame
     };
     addMenuActionAndAccelerator(keyStroke, redoMenuItem, al);
 
-    conservationMenuItem.setText(MessageManager
-            .getString("action.by_conservation"));
-    conservationMenuItem.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        conservationMenuItem_actionPerformed();
-      }
-    });
-    noColourmenuItem.setText(MessageManager.getString("label.none"));
-    noColourmenuItem.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        noColourmenuItem_actionPerformed(e);
-      }
-    });
     wrapMenuItem.setText(MessageManager.getString("label.wrap"));
     wrapMenuItem.addActionListener(new ActionListener()
     {
@@ -1184,16 +804,6 @@ public class GAlignFrame extends JInternalFrame
     };
     addMenuActionAndAccelerator(keyStroke, findMenuItem, al);
 
-    abovePIDThreshold.setText(MessageManager
-            .getString("label.above_identity_threshold"));
-    abovePIDThreshold.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        abovePIDThreshold_actionPerformed();
-      }
-    });
     showSeqFeatures.setText(MessageManager
             .getString("label.show_sequence_features"));
     showSeqFeatures.addActionListener(new ActionListener()
@@ -1339,28 +949,6 @@ public class GAlignFrame extends JInternalFrame
       }
     });
 
-    nucleotideColour.setText(MessageManager.getString("label.nucleotide"));
-    nucleotideColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        nucleotideColour_actionPerformed(e);
-      }
-    });
-
-    tcoffeeColour.setText(MessageManager.getString("label.tcoffee_scores"));
-    tcoffeeColour.setEnabled(false);
-    tcoffeeColour.addActionListener(new ActionListener()
-    {
-
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        tcoffeeColorScheme_actionPerformed(e);
-      }
-    });
-
     JMenuItem deleteGroups = new JMenuItem(
             MessageManager.getString("action.undefine_groups"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_U, Toolkit
@@ -1375,6 +963,17 @@ public class GAlignFrame extends JInternalFrame
     };
     addMenuActionAndAccelerator(keyStroke, deleteGroups, al);
 
+    JMenuItem annotationColumn = new JMenuItem(
+            MessageManager.getString("action.select_by_annotation"));
+    annotationColumn.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        annotationColumn_actionPerformed(e);
+      }
+    });
+
     JMenuItem createGroup = new JMenuItem(
             MessageManager.getString("action.create_groups"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_G, Toolkit
@@ -1472,16 +1071,6 @@ public class GAlignFrame extends JInternalFrame
     };
     addMenuActionAndAccelerator(keyStroke, pasteThis, al);
 
-    applyToAllGroups.setText(MessageManager
-            .getString("label.apply_colour_to_all_groups"));
-    applyToAllGroups.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        applyToAllGroups_actionPerformed(e);
-      }
-    });
     JMenuItem createPNG = new JMenuItem("PNG");
     createPNG.addActionListener(new ActionListener()
     {
@@ -1606,26 +1195,6 @@ public class GAlignFrame extends JInternalFrame
 
     });
 
-    modifyPID = new JMenuItem(
-            MessageManager.getString("label.modify_identity_threshold"));
-    modifyPID.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        modifyPID_actionPerformed();
-      }
-    });
-    modifyConservation.setText(MessageManager
-            .getString("label.modify_conservation_threshold"));
-    modifyConservation.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        modifyConservation_actionPerformed();
-      }
-    });
     sortByTreeMenu
             .setText(MessageManager.getString("action.by_tree_order"));
     sort.setText(MessageManager.getString("action.sort"));
@@ -1775,39 +1344,6 @@ public class GAlignFrame extends JInternalFrame
       }
     });
 
-    JMenuItem annotationColour = new JMenuItem(
-            MessageManager.getString("action.by_annotation"));
-    annotationColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        annotationColour_actionPerformed(e);
-      }
-    });
-
-    JMenuItem annotationColumn = new JMenuItem(
-            MessageManager.getString("action.select_by_annotation"));
-    annotationColumn.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        annotationColumn_actionPerformed(e);
-      }
-    });
-
-    rnahelicesColour.setText(MessageManager
-            .getString("action.by_rna_helixes"));
-    rnahelicesColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        rnahelicesColour_actionPerformed(e);
-      }
-    });
-
     JMenuItem associatedData = new JMenuItem(
             MessageManager.getString("label.load_features_annotations"));
     associatedData.addActionListener(new ActionListener()
@@ -2114,16 +1650,7 @@ public class GAlignFrame extends JInternalFrame
     tabbedPane.setToolTipText("<html><i>"
             + MessageManager.getString("label.rename_tab_eXpand_reGroup")
             + "</i></html>");
-    JMenuItem textColour = new JMenuItem(
-            MessageManager.getString("action.set_text_colour"));
-    textColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        textColour_actionPerformed(e);
-      }
-    });
+
     formatMenu.setText(MessageManager.getString("action.format"));
     JMenu selectMenu = new JMenu(MessageManager.getString("action.select"));
     idRightAlign.setText(MessageManager
@@ -2305,33 +1832,6 @@ public class GAlignFrame extends JInternalFrame
     autoAnnMenu.add(showGroupConsensus);
     annotationsMenu.add(autoAnnMenu);
 
-    colourMenu.add(applyToAllGroups);
-    colourMenu.add(textColour);
-    colourMenu.addSeparator();
-    colourMenu.add(noColourmenuItem);
-    colourMenu.add(clustalColour);
-    colourMenu.add(BLOSUM62Colour);
-    colourMenu.add(PIDColour);
-    colourMenu.add(zappoColour);
-    colourMenu.add(taylorColour);
-    colourMenu.add(hydrophobicityColour);
-    colourMenu.add(helixColour);
-    colourMenu.add(strandColour);
-    colourMenu.add(turnColour);
-    colourMenu.add(buriedColour);
-    colourMenu.add(nucleotideColour);
-    colourMenu.add(purinePyrimidineColour);
-    // colourMenu.add(RNAInteractionColour);
-    // colourMenu.add(covariationColour);
-    colourMenu.add(tcoffeeColour);
-    colourMenu.add(userDefinedColour);
-    colourMenu.addSeparator();
-    colourMenu.add(conservationMenuItem);
-    colourMenu.add(modifyConservation);
-    colourMenu.add(abovePIDThreshold);
-    colourMenu.add(modifyPID);
-    colourMenu.add(annotationColour);
-    colourMenu.add(rnahelicesColour);
 
     sort.add(sortIDMenuItem);
     sort.add(sortLengthMenuItem);
@@ -2404,6 +1904,90 @@ public class GAlignFrame extends JInternalFrame
     // selectMenu.add(listenToViewSelections);
   }
 
+  /**
+   * Constructs the entries on the Colour menu (but does not add them to the
+   * menu).
+   */
+  protected void initColourMenu()
+  {
+    applyToAllGroups = new JCheckBoxMenuItem(
+            MessageManager.getString("label.apply_colour_to_all_groups"));
+    applyToAllGroups.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        applyToAllGroups_actionPerformed(applyToAllGroups.isSelected());
+      }
+    });
+
+    textColour = new JRadioButtonMenuItem(
+            MessageManager.getString("action.set_text_colour"));
+    textColour.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        textColour_actionPerformed();
+      }
+    });
+
+    conservationMenuItem = new JCheckBoxMenuItem(
+            MessageManager.getString("action.by_conservation"));
+    conservationMenuItem.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        conservationMenuItem_actionPerformed(conservationMenuItem
+                .isSelected());
+      }
+    });
+
+    abovePIDThreshold = new JCheckBoxMenuItem(
+            MessageManager.getString("label.above_identity_threshold"));
+    abovePIDThreshold.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        abovePIDThreshold_actionPerformed(abovePIDThreshold.isSelected());
+      }
+    });
+    modifyPID = new JMenuItem(
+            MessageManager.getString("label.modify_identity_threshold"));
+    modifyPID.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        modifyPID_actionPerformed();
+      }
+    });
+    modifyConservation = new JMenuItem(
+            MessageManager
+            .getString("label.modify_conservation_threshold"));
+    modifyConservation.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        modifyConservation_actionPerformed();
+      }
+    });
+
+    annotationColour = new JMenuItem(
+            MessageManager.getString("action.by_annotation"));
+    annotationColour.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        annotationColour_actionPerformed();
+      }
+    });
+  }
+
   protected void selectHighlightedColumns_actionPerformed(
           ActionEvent actionEvent)
   {
@@ -2759,67 +2343,7 @@ public class GAlignFrame extends JInternalFrame
   {
   }
 
-  protected void clustalColour_actionPerformed(ActionEvent e)
-  {
-  }
-
-  protected void zappoColour_actionPerformed(ActionEvent e)
-  {
-  }
-
-  protected void taylorColour_actionPerformed(ActionEvent e)
-  {
-  }
-
-  protected void hydrophobicityColour_actionPerformed(ActionEvent e)
-  {
-  }
-
-  protected void helixColour_actionPerformed(ActionEvent e)
-  {
-  }
-
-  protected void strandColour_actionPerformed(ActionEvent e)
-  {
-  }
-
-  protected void turnColour_actionPerformed(ActionEvent e)
-  {
-  }
-
-  protected void buriedColour_actionPerformed(ActionEvent e)
-  {
-  }
-
-  protected void userDefinedColour_actionPerformed(ActionEvent e)
-  {
-  }
-
-  protected void PIDColour_actionPerformed(ActionEvent e)
-  {
-  }
-
-  protected void BLOSUM62Colour_actionPerformed(ActionEvent e)
-  {
-  }
-
-  protected void purinePyrimidineColour_actionPerformed(ActionEvent e)
-  {
-  }
-
-  protected void RNAInteractionColour_actionPerformed(ActionEvent e)
-  {
-  }
-
-  /*
-   * protected void covariationColour_actionPerformed(ActionEvent e) { }
-   */
-
-  protected void noColourmenuItem_actionPerformed(ActionEvent e)
-  {
-  }
-
-  protected void conservationMenuItem_actionPerformed()
+  protected void conservationMenuItem_actionPerformed(boolean selected)
   {
   }
 
@@ -2835,7 +2359,7 @@ public class GAlignFrame extends JInternalFrame
   {
   }
 
-  protected void abovePIDThreshold_actionPerformed()
+  protected void abovePIDThreshold_actionPerformed(boolean selected)
   {
   }
 
@@ -2843,10 +2367,6 @@ public class GAlignFrame extends JInternalFrame
   {
   }
 
-  protected void nucleotideColour_actionPerformed(ActionEvent e)
-  {
-  }
-
   protected void deleteGroups_actionPerformed(ActionEvent e)
   {
   }
@@ -2879,7 +2399,7 @@ public class GAlignFrame extends JInternalFrame
   {
   }
 
-  protected void applyToAllGroups_actionPerformed(ActionEvent e)
+  protected void applyToAllGroups_actionPerformed(boolean selected)
   {
   }
 
@@ -2927,19 +2447,6 @@ public class GAlignFrame extends JInternalFrame
 
   }
 
-  /**
-   * Template method to handle the 'Color T-Coffee scores' menu event.
-   * <p>
-   * Subclasses override this method to provide a custom action.
-   * 
-   * @param event
-   *          The raised event
-   */
-  protected void tcoffeeColorScheme_actionPerformed(ActionEvent event)
-  {
-
-  }
-
   protected void jpred_actionPerformed(ActionEvent e)
   {
   }
@@ -3002,19 +2509,12 @@ public class GAlignFrame extends JInternalFrame
 
   }
 
-  public void annotationColour_actionPerformed(ActionEvent e)
+  public void annotationColour_actionPerformed()
   {
-
   }
 
   public void annotationColumn_actionPerformed(ActionEvent e)
   {
-
-  }
-
-  public void rnahelicesColour_actionPerformed(ActionEvent e)
-  {
-
   }
 
   public void associatedData_actionPerformed(ActionEvent e)
@@ -3107,7 +2607,7 @@ public class GAlignFrame extends JInternalFrame
 
   }
 
-  public void textColour_actionPerformed(ActionEvent e)
+  public void textColour_actionPerformed()
   {
 
   }
index bd0f1de..6b89ab4 100644 (file)
 package jalview.jbgui;
 
 import jalview.api.structures.JalviewStructureDisplayI;
+import jalview.gui.ColourMenuHelper.ColourChangeListener;
 import jalview.util.MessageManager;
 
+import java.awt.BorderLayout;
 import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 
-import javax.swing.ButtonGroup;
 import javax.swing.JInternalFrame;
 import javax.swing.JLabel;
 import javax.swing.JMenu;
@@ -37,53 +38,37 @@ import javax.swing.JPanel;
 import javax.swing.JRadioButtonMenuItem;
 
 public abstract class GStructureViewer extends JInternalFrame implements
-        JalviewStructureDisplayI
+        JalviewStructureDisplayI, ColourChangeListener
 {
   // private AAStructureBindingModel bindingModel;
 
-  protected JMenu savemenu = new JMenu();
+  protected JMenu savemenu;
 
-  protected JMenu viewMenu = new JMenu();
+  protected JMenu viewMenu;
 
-  protected JMenu chainMenu = new JMenu();
+  protected JMenu colourMenu;
 
-  protected JMenu viewerActionMenu = new JMenu();
+  protected JMenu chainMenu;
 
-  protected JMenuItem alignStructs = new JMenuItem();
+  protected JMenu viewerActionMenu;
 
-  protected JMenuItem fitToWindow = new JMenuItem();
+  protected JMenuItem alignStructs;
 
-  protected JRadioButtonMenuItem seqColour = new JRadioButtonMenuItem();
+  protected JMenuItem fitToWindow;
 
-  protected JRadioButtonMenuItem chainColour = new JRadioButtonMenuItem();
+  protected JRadioButtonMenuItem seqColour;
 
-  protected JRadioButtonMenuItem chargeColour = new JRadioButtonMenuItem();
+  protected JRadioButtonMenuItem chainColour;
 
-  protected JRadioButtonMenuItem zappoColour = new JRadioButtonMenuItem();
+  protected JRadioButtonMenuItem chargeColour;
 
-  protected JRadioButtonMenuItem taylorColour = new JRadioButtonMenuItem();
+  protected JRadioButtonMenuItem viewerColour;
 
-  protected JRadioButtonMenuItem hydroColour = new JRadioButtonMenuItem();
+  protected JMenuItem helpItem;
 
-  protected JRadioButtonMenuItem strandColour = new JRadioButtonMenuItem();
+  protected JLabel statusBar;
 
-  protected JRadioButtonMenuItem helixColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem turnColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem buriedColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem purinePyrimidineColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem userColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem viewerColour = new JRadioButtonMenuItem();
-
-  protected JMenuItem helpItem = new JMenuItem();
-
-  protected JLabel statusBar = new JLabel();
-
-  protected JPanel statusPanel = new JPanel();
+  protected JPanel statusPanel;
 
   /**
    * Constructor
@@ -107,6 +92,7 @@ public abstract class GStructureViewer extends JInternalFrame implements
     JMenu fileMenu = new JMenu();
     fileMenu.setText(MessageManager.getString("action.file"));
 
+    savemenu = new JMenu();
     savemenu.setActionCommand(MessageManager.getString("action.save_image"));
     savemenu.setText(MessageManager.getString("action.save_as"));
 
@@ -153,10 +139,14 @@ public abstract class GStructureViewer extends JInternalFrame implements
         viewMapping_actionPerformed(actionEvent);
       }
     });
+
+    viewMenu = new JMenu();
     viewMenu.setText(MessageManager.getString("action.view"));
 
+    chainMenu = new JMenu();
     chainMenu.setText(MessageManager.getString("action.show_chain"));
 
+    fitToWindow = new JMenuItem();
     fitToWindow.setText(MessageManager.getString("label.fit_to_window"));
     fitToWindow.addActionListener(new ActionListener()
     {
@@ -167,148 +157,9 @@ public abstract class GStructureViewer extends JInternalFrame implements
       }
     });
 
-    JMenu colourMenu = new JMenu();
-    colourMenu.setText(MessageManager.getString("label.colours"));
-
-    JMenuItem backGround = new JMenuItem();
-    backGround
-            .setText(MessageManager.getString("action.background_colour"));
-    backGround.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent actionEvent)
-      {
-        backGround_actionPerformed(actionEvent);
-      }
-    });
-    seqColour.setSelected(false);
-    seqColour.setText(MessageManager.getString("action.by_sequence"));
-    seqColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent actionEvent)
-      {
-        seqColour_actionPerformed(actionEvent);
-      }
-    });
-    chainColour.setText(MessageManager.getString("action.by_chain"));
-    chainColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent actionEvent)
-      {
-        chainColour_actionPerformed(actionEvent);
-      }
-    });
-    chargeColour.setText(MessageManager.getString("label.charge_cysteine"));
-    chargeColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent actionEvent)
-      {
-        chargeColour_actionPerformed(actionEvent);
-      }
-    });
-    zappoColour.setText(MessageManager.getString("label.zappo"));
-    zappoColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent actionEvent)
-      {
-        zappoColour_actionPerformed(actionEvent);
-      }
-    });
-    taylorColour.setText(MessageManager.getString("label.taylor"));
-    taylorColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent actionEvent)
-      {
-        taylorColour_actionPerformed(actionEvent);
-      }
-    });
-    hydroColour.setText(MessageManager.getString("label.hydrophobicity"));
-    hydroColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent actionEvent)
-      {
-        hydroColour_actionPerformed(actionEvent);
-      }
-    });
-    strandColour.setText(MessageManager
-            .getString("label.strand_propensity"));
-    strandColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent actionEvent)
-      {
-        strandColour_actionPerformed(actionEvent);
-      }
-    });
-    helixColour.setText(MessageManager.getString("label.helix_propensity"));
-    helixColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent actionEvent)
-      {
-        helixColour_actionPerformed(actionEvent);
-      }
-    });
-    turnColour.setText(MessageManager.getString("label.turn_propensity"));
-    turnColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent actionEvent)
-      {
-        turnColour_actionPerformed(actionEvent);
-      }
-    });
-    buriedColour.setText(MessageManager.getString("label.buried_index"));
-    buriedColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent actionEvent)
-      {
-        buriedColour_actionPerformed(actionEvent);
-      }
-    });
-    purinePyrimidineColour.setText(MessageManager
-            .getString("label.purine_pyrimidine"));
-    purinePyrimidineColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent actionEvent)
-      {
-        purinePyrimidineColour_actionPerformed(actionEvent);
-      }
-    });
-
-    userColour.setText(MessageManager.getString("action.user_defined"));
-    userColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent actionEvent)
-      {
-        userColour_actionPerformed(actionEvent);
-      }
-    });
-    viewerColour.setSelected(false);
-    viewerColour
-            .setText(MessageManager.getString("label.colour_with_jmol"));
-    viewerColour.setToolTipText(MessageManager
-            .getString("label.let_jmol_manage_structure_colours"));
-    viewerColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent actionEvent)
-      {
-        viewerColour_actionPerformed(actionEvent);
-      }
-    });
-
     JMenu helpMenu = new JMenu();
     helpMenu.setText(MessageManager.getString("action.help"));
+    helpItem = new JMenuItem();
     helpItem.setText(MessageManager.getString("label.jmol_help"));
     helpItem.addActionListener(new ActionListener()
     {
@@ -318,6 +169,7 @@ public abstract class GStructureViewer extends JInternalFrame implements
         showHelp_actionPerformed(actionEvent);
       }
     });
+    alignStructs = new JMenuItem();
     alignStructs
             .setText(MessageManager.getString("label.align_structures"));
     alignStructs.addActionListener(new ActionListener()
@@ -328,56 +180,30 @@ public abstract class GStructureViewer extends JInternalFrame implements
         alignStructs_actionPerformed(actionEvent);
       }
     });
-    viewerActionMenu.setText(MessageManager.getString("label.jmol"));
-    menuBar.add(fileMenu);
-    menuBar.add(viewMenu);
-    menuBar.add(colourMenu);
-    menuBar.add(viewerActionMenu);
+
+    viewerActionMenu = new JMenu();
     viewerActionMenu.setVisible(false);
-    menuBar.add(helpMenu);
+    viewerActionMenu.add(alignStructs);
+    colourMenu = new JMenu();
+    colourMenu.setText(MessageManager.getString("label.colours"));
     fileMenu.add(savemenu);
     fileMenu.add(viewMapping);
     savemenu.add(pdbFile);
     savemenu.add(png);
     savemenu.add(eps);
     viewMenu.add(chainMenu);
-
-    colourMenu.add(seqColour);
-    colourMenu.add(chainColour);
-    colourMenu.add(chargeColour);
-    colourMenu.add(zappoColour);
-    colourMenu.add(taylorColour);
-    colourMenu.add(hydroColour);
-    colourMenu.add(helixColour);
-    colourMenu.add(strandColour);
-    colourMenu.add(turnColour);
-    colourMenu.add(buriedColour);
-    colourMenu.add(purinePyrimidineColour);
-    colourMenu.add(userColour);
-    colourMenu.add(viewerColour);
-    colourMenu.add(backGround);
-
-    ButtonGroup colourButtons = new ButtonGroup();
-
-    colourButtons.add(seqColour);
-    colourButtons.add(chainColour);
-    colourButtons.add(chargeColour);
-    colourButtons.add(zappoColour);
-    colourButtons.add(taylorColour);
-    colourButtons.add(hydroColour);
-    colourButtons.add(helixColour);
-    colourButtons.add(strandColour);
-    colourButtons.add(turnColour);
-    colourButtons.add(buriedColour);
-    colourButtons.add(purinePyrimidineColour);
-    colourButtons.add(userColour);
-    colourButtons.add(viewerColour);
-
     helpMenu.add(helpItem);
-    viewerActionMenu.add(alignStructs);
 
+    menuBar.add(fileMenu);
+    menuBar.add(viewMenu);
+    menuBar.add(colourMenu);
+    menuBar.add(viewerActionMenu);
+    menuBar.add(helpMenu);
+
+    statusPanel = new JPanel();
     statusPanel.setLayout(new GridLayout());
-    this.getContentPane().add(statusPanel, java.awt.BorderLayout.SOUTH);
+    this.getContentPane().add(statusPanel, BorderLayout.SOUTH);
+    statusBar = new JLabel();
     statusPanel.add(statusBar, null);
   }
 
@@ -432,52 +258,7 @@ public abstract class GStructureViewer extends JInternalFrame implements
 
   }
 
-  public void zappoColour_actionPerformed(ActionEvent actionEvent)
-  {
-
-  }
-
-  public void taylorColour_actionPerformed(ActionEvent actionEvent)
-  {
-
-  }
-
-  public void hydroColour_actionPerformed(ActionEvent actionEvent)
-  {
-
-  }
-
-  public void helixColour_actionPerformed(ActionEvent actionEvent)
-  {
-
-  }
-
-  public void strandColour_actionPerformed(ActionEvent actionEvent)
-  {
-
-  }
-
-  public void turnColour_actionPerformed(ActionEvent actionEvent)
-  {
-
-  }
-
-  public void buriedColour_actionPerformed(ActionEvent actionEvent)
-  {
-
-  }
-
-  public void purinePyrimidineColour_actionPerformed(ActionEvent actionEvent)
-  {
-
-  }
-
-  public void userColour_actionPerformed(ActionEvent actionEvent)
-  {
-
-  }
-
-  public void backGround_actionPerformed(ActionEvent actionEvent)
+  public void background_actionPerformed(ActionEvent actionEvent)
   {
 
   }
@@ -486,14 +267,4 @@ public abstract class GStructureViewer extends JInternalFrame implements
   {
 
   }
-
-  // {
-  // return bindingModel;
-  // }
-
-  // public void setBindingModel(AAStructureBindingModel bindingModel)
-  // {
-  // this.bindingModel = bindingModel;
-  // }
-
 }
index b5695b2..fe20baf 100755 (executable)
@@ -32,6 +32,8 @@ import java.awt.GridBagLayout;
 import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
@@ -104,6 +106,8 @@ public class GUserDefinedColours extends JPanel
 
   protected JButton lcaseColour = new JButton();
 
+  protected List<JButton> selectedButtons;
+
   /**
    * Creates a new GUserDefinedColours object.
    */
@@ -135,24 +139,27 @@ public class GUserDefinedColours extends JPanel
     okButton.setText(MessageManager.getString("action.ok"));
     okButton.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
-        okButton_actionPerformed(e);
+        okButton_actionPerformed();
       }
     });
     applyButton.setFont(new java.awt.Font("Verdana", 0, 11));
     applyButton.setText(MessageManager.getString("action.apply"));
-    applyButton.addActionListener(new java.awt.event.ActionListener()
+    applyButton.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
-        applyButton_actionPerformed(e);
+        applyButton_actionPerformed();
       }
     });
     loadbutton.setFont(new java.awt.Font("Verdana", 0, 11));
     loadbutton.setText(MessageManager.getString("action.load_scheme"));
     loadbutton.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         loadbutton_actionPerformed(e);
@@ -162,6 +169,7 @@ public class GUserDefinedColours extends JPanel
     savebutton.setText(MessageManager.getString("action.save_scheme"));
     savebutton.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         savebutton_actionPerformed(e);
@@ -171,6 +179,7 @@ public class GUserDefinedColours extends JPanel
     cancelButton.setText(MessageManager.getString("action.cancel"));
     cancelButton.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         cancelButton_actionPerformed(e);
@@ -206,6 +215,7 @@ public class GUserDefinedColours extends JPanel
     caseSensitive.setText(MessageManager.getString("label.case_sensitive"));
     caseSensitive.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         caseSensitive_actionPerformed(e);
@@ -215,6 +225,7 @@ public class GUserDefinedColours extends JPanel
             .setText(MessageManager.getString("label.lower_case_colour"));
     lcaseColour.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         lcaseColour_actionPerformed(e);
@@ -253,25 +264,21 @@ public class GUserDefinedColours extends JPanel
       colorChooser
               .setChooserPanels(new AbstractColorChooserPanel[] { choosers[0] });
     }
+
+    selectedButtons = new ArrayList<JButton>();
   }
 
   /**
    * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
    */
-  protected void okButton_actionPerformed(ActionEvent e)
+  protected void okButton_actionPerformed()
   {
   }
 
   /**
    * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
    */
-  protected void applyButton_actionPerformed(ActionEvent e)
+  protected void applyButton_actionPerformed()
   {
   }
 
index a0e530c..6f84a2e 100644 (file)
@@ -30,7 +30,9 @@ import jalview.datamodel.Annotation;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.ProfilesI;
 import jalview.schemes.ColourSchemeI;
+import jalview.schemes.NucleotideColourScheme;
 import jalview.schemes.ResidueProperties;
+import jalview.schemes.ZappoColourScheme;
 import jalview.util.Platform;
 
 import java.awt.BasicStroke;
@@ -70,7 +72,7 @@ public class AnnotationRenderer
   boolean av_renderHistogram = true, av_renderProfile = true,
           av_normaliseProfile = false;
 
-  ColourSchemeI profcolour = null;
+  ResidueShaderI profcolour = null;
 
   private ColumnSelection columnSelection;
 
@@ -312,13 +314,17 @@ public class AnnotationRenderer
     av_renderHistogram = av.isShowConsensusHistogram();
     av_renderProfile = av.isShowSequenceLogo();
     av_normaliseProfile = av.isNormaliseSequenceLogo();
-    profcolour = av.getGlobalColourScheme();
-    if (profcolour == null)
+    profcolour = av.getResidueShading();
+    if (profcolour == null || profcolour.getColourScheme() == null)
     {
-      // Set the default colour for sequence logo if the alignnent has no
-      // colourscheme set
-      profcolour = av.getAlignment().isNucleotide() ? new jalview.schemes.NucleotideColourScheme()
-              : new jalview.schemes.ZappoColourScheme();
+      /*
+       * Use default colour for sequence logo if 
+       * the alignment has no colourscheme set
+       * (would like to use user preference but n/a for applet)
+       */
+      ColourSchemeI col = av.getAlignment().isNucleotide() ? new NucleotideColourScheme()
+              : new ZappoColourScheme();
+      profcolour = new ResidueShader(col);
     }
     columnSelection = av.getColumnSelection();
     hconsensus = av.getSequenceConsensusHash();
diff --git a/src/jalview/renderer/ResidueShader.java b/src/jalview/renderer/ResidueShader.java
new file mode 100644 (file)
index 0000000..3f5cd11
--- /dev/null
@@ -0,0 +1,375 @@
+package jalview.renderer;
+
+import jalview.analysis.Conservation;
+import jalview.api.ViewStyleI;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+import jalview.schemes.ColourSchemeI;
+import jalview.util.ColorUtils;
+import jalview.util.Comparison;
+
+import java.awt.Color;
+import java.util.Map;
+
+/**
+ * A class that computes the colouring of an alignment (or subgroup). Currently
+ * the factors that may influence residue colouring are
+ * <ul>
+ * <li>the colour scheme that provides a colour for each aligned residue</li>
+ * <li>any threshold for colour, based on percentage identity with consensus</li>
+ * <li>any graduation based on conservation of physico-chemical properties</li>
+ * </ul>
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class ResidueShader implements ResidueShaderI
+{
+  private static final int INITIAL_CONSERVATION = 30;
+
+  /*
+   * the colour scheme that gives the colour of each residue
+   * before applying any conservation or PID shading
+   */
+  private ColourSchemeI colourScheme;
+
+  /*
+   * the consensus data for each column
+   */
+  private ProfilesI consensus;
+
+  /*
+   * if true, apply shading of colour by conservation
+   */
+  private boolean conservationColouring;
+
+  /*
+   * the phsyico-chemical property conservation scores for columns, with values
+   * 0-9, '+' (all properties conserved), '*' (residue fully conserved) or '-' (gap)
+   * (may be null if colour by conservation is not selected)
+   */
+  private char[] conservation;
+
+  /*
+   * minimum percentage identity for colour to be applied;
+   * if above zero, residue must match consensus (or joint consensus)
+   * and column have >= pidThreshold identity with the residue
+   */
+  private int pidThreshold;
+
+  /*
+   * if true, ignore gaps in percentage identity calculation
+   */
+  private boolean ignoreGaps;
+
+  /*
+   * setting of the By Conservation slider
+   */
+  private int conservationIncrement = INITIAL_CONSERVATION;
+
+  public ResidueShader(ColourSchemeI cs)
+  {
+    colourScheme = cs;
+  }
+
+  /**
+   * Default constructor
+   */
+  public ResidueShader()
+  {
+  }
+
+  /**
+   * Constructor given view style settings
+   * 
+   * @param viewStyle
+   */
+  public ResidueShader(ViewStyleI viewStyle)
+  {
+    // TODO remove duplicated storing of conservation / pid thresholds?
+    this();
+    setConservationApplied(viewStyle.isConservationColourSelected());
+    // setThreshold(viewStyle.getThreshold());
+  }
+
+  /**
+   * @see jalview.renderer.ResidueShaderI#setConsensus(jalview.datamodel.ProfilesI)
+   */
+  @Override
+  public void setConsensus(ProfilesI cons)
+  {
+    consensus = cons;
+  }
+
+  /**
+   * @see jalview.renderer.ResidueShaderI#conservationApplied()
+   */
+  @Override
+  public boolean conservationApplied()
+  {
+    return conservationColouring;
+  }
+
+  /**
+   * @see jalview.renderer.ResidueShaderI#setConservationApplied(boolean)
+   */
+  @Override
+  public void setConservationApplied(boolean conservationApplied)
+  {
+    conservationColouring = conservationApplied;
+  }
+
+  /**
+   * @see jalview.renderer.ResidueShaderI#setConservation(jalview.analysis.Conservation)
+   */
+  @Override
+  public void setConservation(Conservation cons)
+  {
+    if (cons == null)
+    {
+      conservationColouring = false;
+      conservation = null;
+    }
+    else
+    {
+      conservationColouring = true;
+      conservation = cons.getConsSequence().getSequenceAsString()
+              .toCharArray();
+    }
+  
+  }
+
+  /**
+   * @see jalview.renderer.ResidueShaderI#alignmentChanged(jalview.datamodel.AnnotatedCollectionI,
+   *      java.util.Map)
+   */
+  @Override
+  public void alignmentChanged(AnnotatedCollectionI alignment,
+          Map<SequenceI, SequenceCollectionI> hiddenReps)
+  {
+    if (colourScheme != null)
+    {
+      colourScheme.alignmentChanged(alignment, hiddenReps);
+    }
+  }
+
+  /**
+   * @see jalview.renderer.ResidueShaderI#setThreshold(int, boolean)
+   */
+  @Override
+  public void setThreshold(int consensusThreshold, boolean ignoreGaps)
+  {
+    pidThreshold = consensusThreshold;
+    this.ignoreGaps = ignoreGaps;
+  }
+
+  /**
+   * @see jalview.renderer.ResidueShaderI#setConservationInc(int)
+   */
+  @Override
+  public void setConservationInc(int i)
+  {
+    conservationIncrement = i;
+  }
+
+  /**
+   * @see jalview.renderer.ResidueShaderI#getConservationInc()
+   */
+  @Override
+  public int getConservationInc()
+  {
+    return conservationIncrement;
+  }
+
+  /**
+   * @see jalview.renderer.ResidueShaderI#getThreshold()
+   */
+  @Override
+  public int getThreshold()
+  {
+    return pidThreshold;
+  }
+
+  /**
+   * @see jalview.renderer.ResidueShaderI#findColour(char, int,
+   *      jalview.datamodel.SequenceI)
+   */
+  @Override
+  public Color findColour(char symbol, int position, SequenceI seq)
+  {
+    /*
+     * get 'base' colour
+     */
+    ProfileI profile = consensus == null ? null : consensus.get(position);
+    String modalResidue = profile == null ? null : profile
+            .getModalResidue();
+    float pid = profile == null ? 0f : profile
+            .getPercentageIdentity(ignoreGaps);
+    Color colour = colourScheme == null ? Color.white : colourScheme
+            .findColour(symbol, position, seq, modalResidue, pid);
+
+    /*
+     * apply PID threshold and consensus fading if in force
+     */
+    colour = adjustColour(symbol, position, colour);
+
+    return colour;
+  }
+
+  /**
+   * Adjusts colour by applying thresholding or conservation shading, if in
+   * force. That is
+   * <ul>
+   * <li>if there is a threshold set for colouring, and the residue doesn't
+   * match the consensus (or a joint consensus) residue, or the consensus score
+   * is not above the threshold, then the colour is set to white</li>
+   * <li>if conservation colouring is selected, the colour is faded by an amount
+   * depending on the conservation score for the column, and the conservation
+   * colour threshold</li>
+   * </ul>
+   * 
+   * @param symbol
+   * @param column
+   * @param colour
+   * @return
+   */
+  protected Color adjustColour(char symbol, int column, Color colour)
+  {
+    if (!aboveThreshold(symbol, column))
+    {
+      colour = Color.white;
+    }
+  
+    if (conservationColouring)
+    {
+      colour = applyConservation(colour, column);
+    }
+    return colour;
+  }
+
+  /**
+   * Answers true if there is a consensus profile for the specified column, and
+   * the given residue matches the consensus (or joint consensus) residue for
+   * the column, and the percentage identity for the profile is equal to or
+   * greater than the current threshold; else answers false. The percentage
+   * calculation depends on whether or not we are ignoring gapped sequences.
+   * 
+   * @param residue
+   * @param column
+   *          (index into consensus profiles)
+   * 
+   * @return
+   * @see #setThreshold(int, boolean)
+   */
+  protected boolean aboveThreshold(char residue, int column)
+  {
+    if (pidThreshold == 0)
+    {
+      return true;
+    }
+    if ('a' <= residue && residue <= 'z')
+    {
+      // TO UPPERCASE !!!
+      // Faster than toUpperCase
+      residue -= ('a' - 'A');
+    }
+  
+    if (consensus == null)
+    {
+      return false;
+    }
+  
+    ProfileI profile = consensus.get(column);
+  
+    /*
+     * test whether this is the consensus (or joint consensus) residue
+     */
+    if (profile != null
+            && profile.getModalResidue().contains(String.valueOf(residue)))
+    {
+      if (profile.getPercentageIdentity(ignoreGaps) >= pidThreshold)
+      {
+        return true;
+      }
+    }
+  
+    return false;
+  }
+
+  /**
+   * Applies a combination of column conservation score, and conservation
+   * percentage slider, to 'bleach' out the residue colours towards white.
+   * <p>
+   * If a column is fully conserved (identical residues, conservation score 11,
+   * shown as *), or all 10 physico-chemical properties are conserved
+   * (conservation score 10, shown as +), then the colour is left unchanged.
+   * <p>
+   * Otherwise a 'bleaching' factor is computed and applied to the colour. This
+   * is designed to fade colours for scores of 0-9 completely to white at slider
+   * positions ranging from 18% - 100% respectively.
+   * 
+   * @param currentColour
+   * @param column
+   * 
+   * @return bleached (or unmodified) colour
+   */
+  protected Color applyConservation(Color currentColour, int column)
+  {
+    if (conservation == null || conservation.length <= column)
+    {
+      return currentColour;
+    }
+    char conservationScore = conservation[column];
+  
+    /*
+     * if residues are fully conserved (* or 11), or all properties
+     * are conserved (+ or 10), leave colour unchanged
+     */
+    if (conservationScore == '*' || conservationScore == '+'
+            || conservationScore == (char) 10
+            || conservationScore == (char) 11)
+    {
+      return currentColour;
+    }
+  
+    if (Comparison.isGap(conservationScore))
+    {
+      return Color.white;
+    }
+  
+    /*
+     * convert score 0-9 to a bleaching factor 1.1 - 0.2
+     */
+    float bleachFactor = (11 - (conservationScore - '0')) / 10f;
+  
+    /*
+     * scale this up by 0-5 (percentage slider / 20)
+     * as a result, scores of:         0  1  2  3  4  5  6  7  8  9
+     * fade to white at slider value: 18 20 22 25 29 33 40 50 67 100%
+     */
+    bleachFactor *= (conservationIncrement / 20f);
+  
+    return ColorUtils.bleachColour(currentColour, bleachFactor);
+  }
+
+  /**
+   * @see jalview.renderer.ResidueShaderI#getColourScheme()
+   */
+  @Override
+  public ColourSchemeI getColourScheme()
+  {
+    return this.colourScheme;
+  }
+
+  /**
+   * @see jalview.renderer.ResidueShaderI#setColourScheme(jalview.schemes.ColourSchemeI)
+   */
+  @Override
+  public void setColourScheme(ColourSchemeI cs)
+  {
+    colourScheme = cs;
+  }
+}
diff --git a/src/jalview/renderer/ResidueShaderI.java b/src/jalview/renderer/ResidueShaderI.java
new file mode 100644 (file)
index 0000000..a914a1a
--- /dev/null
@@ -0,0 +1,64 @@
+package jalview.renderer;
+
+import jalview.analysis.Conservation;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.ProfilesI;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+import jalview.schemes.ColourSchemeI;
+
+import java.awt.Color;
+import java.util.Map;
+
+public interface ResidueShaderI
+{
+
+  public abstract void setConsensus(ProfilesI cons);
+
+  public abstract boolean conservationApplied();
+
+  public abstract void setConservationApplied(boolean conservationApplied);
+
+  public abstract void setConservation(Conservation cons);
+
+  public abstract void alignmentChanged(AnnotatedCollectionI alignment,
+          Map<SequenceI, SequenceCollectionI> hiddenReps);
+
+  /**
+   * Sets the percentage consensus threshold value, and whether gaps are ignored
+   * in percentage identity calculation
+   * 
+   * @param consensusThreshold
+   * @param ignoreGaps
+   */
+  public abstract void setThreshold(int consensusThreshold,
+          boolean ignoreGaps);
+
+  public abstract void setConservationInc(int i);
+
+  public abstract int getConservationInc();
+
+  /**
+   * Get the percentage threshold for this colour scheme
+   * 
+   * @return Returns the percentage threshold
+   */
+  public abstract int getThreshold();
+
+  /**
+   * Returns the possibly context dependent colour for the given symbol at the
+   * aligned position in the given sequence. For example, the colour may depend
+   * on the symbol's relationship to the consensus residue for the column.
+   * 
+   * @param symbol
+   * @param position
+   * @param seq
+   * @return
+   */
+  public abstract Color findColour(char symbol, int position, SequenceI seq);
+
+  public abstract ColourSchemeI getColourScheme();
+
+  public abstract void setColourScheme(ColourSchemeI cs);
+
+}
\ No newline at end of file
index 89b8f07..1a3e9ef 100755 (executable)
@@ -64,11 +64,11 @@ public class AnnotationColourGradient extends FollowerColourScheme
   IdentityHashMap<SequenceI, AlignmentAnnotation> seqannot = null;
 
   @Override
-  public ColourSchemeI applyTo(AnnotatedCollectionI sg,
+  public ColourSchemeI getInstance(AnnotatedCollectionI sg,
           Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
   {
     AnnotationColourGradient acg = new AnnotationColourGradient(annotation,
-            colourScheme, aboveAnnotationThreshold);
+            getColourScheme(), aboveAnnotationThreshold);
     acg.thresholdIsMinMax = thresholdIsMinMax;
     acg.annotationThreshold = (annotationThreshold == null) ? null
             : new GraphLine(annotationThreshold);
@@ -92,11 +92,12 @@ public class AnnotationColourGradient extends FollowerColourScheme
   {
     if (originalColour instanceof AnnotationColourGradient)
     {
-      colourScheme = ((AnnotationColourGradient) originalColour).colourScheme;
+      setColourScheme(((AnnotationColourGradient) originalColour)
+              .getColourScheme());
     }
     else
     {
-      colourScheme = originalColour;
+      setColourScheme(originalColour);
     }
 
     this.annotation = annotation;
@@ -250,6 +251,7 @@ public class AnnotationColourGradient extends FollowerColourScheme
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public Color findColour(char c)
   {
     return Color.red;
@@ -275,88 +277,89 @@ public class AnnotationColourGradient extends FollowerColourScheme
     {
       return currentColour;
     }
-    if ((threshold == 0) || aboveThreshold(c, j))
+    // if ((threshold == 0) || aboveThreshold(c, j))
+    // {
+    if (annotation.annotations != null && j < annotation.annotations.length
+            && annotation.annotations[j] != null
+            && !jalview.util.Comparison.isGap(c))
     {
-      if (annotation.annotations != null
-              && j < annotation.annotations.length
-              && annotation.annotations[j] != null
-              && !jalview.util.Comparison.isGap(c))
+      Annotation aj = annotation.annotations[j];
+      // 'use original colours' => colourScheme != null
+      // -> look up colour to be used
+      // predefined colours => preconfigured shading
+      // -> only use original colours reference if thresholding enabled &
+      // minmax exists
+      // annotation.hasIcons => null or black colours replaced with glyph
+      // colours
+      // -> reuse original colours if present
+      // -> if thresholding enabled then return colour on non-whitespace glyph
+
+      if (aboveAnnotationThreshold == NO_THRESHOLD
+              || (annotationThreshold != null && (aboveAnnotationThreshold == ABOVE_THRESHOLD ? aj.value >= annotationThreshold.value
+                      : aj.value <= annotationThreshold.value)))
       {
-        Annotation aj = annotation.annotations[j];
-        // 'use original colours' => colourScheme != null
-        // -> look up colour to be used
-        // predefined colours => preconfigured shading
-        // -> only use original colours reference if thresholding enabled &
-        // minmax exists
-        // annotation.hasIcons => null or black colours replaced with glyph
-        // colours
-        // -> reuse original colours if present
-        // -> if thresholding enabled then return colour on non-whitespace glyph
-
-        if (aboveAnnotationThreshold == NO_THRESHOLD
-                || (annotationThreshold != null && (aboveAnnotationThreshold == ABOVE_THRESHOLD ? aj.value >= annotationThreshold.value
-                        : aj.value <= annotationThreshold.value)))
+        if (predefinedColours && aj.colour != null
+                && !aj.colour.equals(Color.black))
         {
-          if (predefinedColours && aj.colour != null
-                  && !aj.colour.equals(Color.black))
-          {
-            currentColour = aj.colour;
-          }
-          else if (annotation.hasIcons
-                  && annotation.graph == AlignmentAnnotation.NO_GRAPH)
+          currentColour = aj.colour;
+        }
+        else if (annotation.hasIcons
+                && annotation.graph == AlignmentAnnotation.NO_GRAPH)
+        {
+          if (aj.secondaryStructure > ' ' && aj.secondaryStructure != '.'
+                  && aj.secondaryStructure != '-')
           {
-            if (aj.secondaryStructure > ' ' && aj.secondaryStructure != '.'
-                    && aj.secondaryStructure != '-')
+            if (getColourScheme() != null)
             {
-              if (colourScheme != null)
+              currentColour = getColourScheme().findColour(c, j, seq, null,
+                      0f);
+            }
+            else
+            {
+              if (annotation.isRNA())
               {
-                currentColour = colourScheme.findColour(c, j, seq);
+                currentColour = ColourSchemeProperty.rnaHelices[(int) aj.value];
               }
               else
               {
-                if (annotation.isRNA())
-                {
-                  currentColour = ColourSchemeProperty.rnaHelices[(int) aj.value];
-                }
-                else
-                {
-                  currentColour = annotation.annotations[j].secondaryStructure == 'H' ? jalview.renderer.AnnotationRenderer.HELIX_COLOUR
-                          : annotation.annotations[j].secondaryStructure == 'E' ? jalview.renderer.AnnotationRenderer.SHEET_COLOUR
-                                  : jalview.renderer.AnnotationRenderer.STEM_COLOUR;
-                }
+                currentColour = annotation.annotations[j].secondaryStructure == 'H' ? jalview.renderer.AnnotationRenderer.HELIX_COLOUR
+                        : annotation.annotations[j].secondaryStructure == 'E' ? jalview.renderer.AnnotationRenderer.SHEET_COLOUR
+                                : jalview.renderer.AnnotationRenderer.STEM_COLOUR;
               }
             }
-            else
-            {
-              //
-              return Color.white;
-            }
           }
-          else if (noGradient)
+          else
           {
-            if (colourScheme != null)
-            {
-              currentColour = colourScheme.findColour(c, j, seq);
-            }
-            else
-            {
-              if (aj.colour != null)
-              {
-                currentColour = aj.colour;
-              }
-            }
+            //
+            return Color.white;
+          }
+        }
+        else if (noGradient)
+        {
+          if (getColourScheme() != null)
+          {
+            currentColour = getColourScheme().findColour(c, j, seq, null,
+                    0f);
           }
           else
           {
-            currentColour = shadeCalculation(annotation, j);
+            if (aj.colour != null)
+            {
+              currentColour = aj.colour;
+            }
           }
         }
-        if (conservationColouring)
+        else
         {
-          currentColour = applyConservation(currentColour, j);
+          currentColour = shadeCalculation(annotation, j);
         }
       }
+      // if (conservationColouring)
+      // {
+      // currentColour = applyConservation(currentColour, j);
+      // }
     }
+    // }
     return currentColour;
   }
 
@@ -419,4 +422,16 @@ public class AnnotationColourGradient extends FollowerColourScheme
   {
     seqAssociated = sassoc;
   }
+
+  @Override
+  public String getSchemeName()
+  {
+    return "Annotation";
+  }
+
+  @Override
+  public boolean isSimple()
+  {
+    return false;
+  }
 }
index c47f171..f35b886 100755 (executable)
@@ -38,73 +38,77 @@ public class Blosum62ColourScheme extends ResidueColourScheme
     super();
   }
 
+  /**
+   * Returns a new instance of this colour scheme with which the given data may
+   * be coloured
+   */
   @Override
-  public Color findColour(char res, int j, SequenceI seq)
+  public ColourSchemeI getInstance(AnnotatedCollectionI coll,
+          Map<SequenceI, SequenceCollectionI> hrs)
   {
+    return new Blosum62ColourScheme();
+  }
+
+  @Override
+  public Color findColour(char res, int j, SequenceI seq,
+          String consensusResidue, float pid)
+  {
+    /*
+     * compare as upper case; note consensusResidue is 
+     * always computed as uppercase
+     */
     if ('a' <= res && res <= 'z')
     {
-      // TO UPPERCASE !!!
       res -= ('a' - 'A');
     }
 
-    if (consensus == null || consensus.get(j) == null
-            || (threshold != 0 && !aboveThreshold(res, j)))
+    if (Comparison.isGap(res) || consensusResidue == null)
     {
       return Color.white;
     }
 
-    Color currentColour;
+    Color colour;
 
-    if (!Comparison.isGap(res))
+    if (consensusResidue.indexOf(res) > -1)
+    {
+      colour = DARK_BLUE;
+    }
+    else
     {
-      /*
-       * test if this is the consensus (or joint consensus) residue
-       */
-      String max = consensus.get(j).getModalResidue();
+      int c = 0;
 
-      if (max.indexOf(res) > -1)
+      for (char consensus : consensusResidue.toCharArray())
       {
-        currentColour = DARK_BLUE;
+        c += ResidueProperties.getBLOSUM62(consensus, res);
       }
-      else
-      {
-        int c = 0;
-        int max_aa = 0;
-        int n = max.length();
 
-        do
-        {
-          c += ResidueProperties.getBLOSUM62(max.charAt(max_aa), res);
-        } while (++max_aa < n);
-
-        if (c > 0)
-        {
-          currentColour = LIGHT_BLUE;
-        }
-        else
-        {
-          currentColour = Color.white;
-        }
+      if (c > 0)
+      {
+        colour = LIGHT_BLUE;
       }
-
-      if (conservationColouring)
+      else
       {
-        currentColour = applyConservation(currentColour, j);
+        colour = Color.white;
       }
     }
-    else
-    {
-      return Color.white;
-    }
+    return colour;
+  }
 
-    return currentColour;
+  @Override
+  public boolean isPeptideSpecific()
+  {
+    return true;
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return JalviewColourScheme.Blosum62.toString();
   }
 
   @Override
-  public ColourSchemeI applyTo(AnnotatedCollectionI sg,
-          Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
+  public boolean isSimple()
   {
-    ColourSchemeI newcs = super.applyTo(sg, hiddenRepSequences);
-    return newcs;
+    return false;
   }
 }
index 3c68da0..a3b85b9 100755 (executable)
  */
 package jalview.schemes;
 
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+
 import java.awt.Color;
+import java.util.Map;
 
 /**
  * DOCUMENT ME!
@@ -47,8 +52,32 @@ public class BuriedColourScheme extends ScoreColourScheme
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public Color makeColour(float c)
   {
     return new Color(0, (float) (1.0 - c), c);
   }
+
+  @Override
+  public boolean isPeptideSpecific()
+  {
+    return true;
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return JalviewColourScheme.Buried.toString();
+  }
+
+  /**
+   * Returns a new instance of this colour scheme with which the given data may
+   * be coloured
+   */
+  @Override
+  public ColourSchemeI getInstance(AnnotatedCollectionI coll,
+          Map<SequenceI, SequenceCollectionI> hrs)
+  {
+    return new BuriedColourScheme();
+  }
 }
index ca4316f..f13a90c 100755 (executable)
@@ -23,9 +23,9 @@ package jalview.schemes;
 import jalview.datamodel.AnnotatedCollectionI;
 import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceI;
+import jalview.util.Comparison;
 
 import java.awt.Color;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -39,10 +39,32 @@ public class ClustalxColourScheme extends ResidueColourScheme
 
   private static final int SIXTY = 60;
 
-  /*
-   * Map from conventional colour names to Clustal version of the same
-   */
-  private static Map<Color, Color> colhash = new HashMap<Color, Color>();
+  enum ClustalColour
+  {
+    RED(0.9f, 0.2f, 0.1f), BLUE(0.5f, 0.7f, 0.9f), GREEN(0.1f, 0.8f, 0.1f),
+    ORANGE(0.9f, 0.6f, 0.3f), CYAN(0.1f, 0.7f, 0.7f),
+    PINK(0.9f, 0.5f, 0.5f), MAGENTA(0.8f, 0.3f, 0.8f), YELLOW(0.8f, 0.8f,
+            0.0f);
+
+    final Color colour;
+
+    ClustalColour(float r, float g, float b)
+    {
+      colour = new Color(r, g, b);
+    }
+  }
+  private class ConsensusColour
+  {
+    Consensus[] cons;
+
+    Color c;
+
+    public ConsensusColour(ClustalColour col, Consensus[] conses)
+    {
+      this.cons = conses;
+      this.c = col.colour;
+    }
+  }
 
   private int[][] cons2;
 
@@ -56,16 +78,12 @@ public class ClustalxColourScheme extends ResidueColourScheme
 
   private boolean includeGaps = true;
 
-  static
+  /**
+   * Default constructor (required for Class.newInstance())
+   */
+  public ClustalxColourScheme()
   {
-    colhash.put(Color.RED, new Color(0.9f, 0.2f, 0.1f));
-    colhash.put(Color.BLUE, new Color(0.5f, 0.7f, 0.9f));
-    colhash.put(Color.GREEN, new Color(0.1f, 0.8f, 0.1f));
-    colhash.put(Color.ORANGE, new Color(0.9f, 0.6f, 0.3f));
-    colhash.put(Color.CYAN, new Color(0.1f, 0.7f, 0.7f));
-    colhash.put(Color.PINK, new Color(0.9f, 0.5f, 0.5f));
-    colhash.put(Color.MAGENTA, new Color(0.8f, 0.3f, 0.8f));
-    colhash.put(Color.YELLOW, new Color(0.8f, 0.8f, 0.0f));
+
   }
 
   public ClustalxColourScheme(AnnotatedCollectionI alignment,
@@ -74,6 +92,7 @@ public class ClustalxColourScheme extends ResidueColourScheme
     alignmentChanged(alignment, hiddenReps);
   }
 
+  @Override
   public void alignmentChanged(AnnotatedCollectionI alignment,
           Map<SequenceI, SequenceCollectionI> hiddenReps)
   {
@@ -83,29 +102,15 @@ public class ClustalxColourScheme extends ResidueColourScheme
     includeGaps = isIncludeGaps(); // does nothing - TODO replace with call to
     // get the current setting of the
     // includeGaps param.
-    int start = 0;
-
-    // Initialize the array
-    for (int j = 0; j < 24; j++)
-    {
-      for (int i = 0; i < maxWidth; i++)
-      {
-        cons2[i][j] = 0;
-      }
-    }
-
-    int res;
-    int i;
-    int j = 0;
-    char[] seq;
+    int res = 0;
 
     for (SequenceI sq : seqs)
     {
-      seq = sq.getSequence();
+      char[] seq = sq.getSequence();
 
       int end_j = seq.length - 1;
 
-      for (i = start; i <= end_j; i++)
+      for (int i = 0; i <= end_j; i++)
       {
         if ((seq.length - 1) < i)
         {
@@ -115,18 +120,15 @@ public class ClustalxColourScheme extends ResidueColourScheme
         {
           res = ResidueProperties.aaIndex[seq[i]];
         }
-
         cons2[i][res]++;
       }
-
-      j++;
     }
 
     this.size = seqs.size();
     makeColours();
   }
 
-  public void makeColours()
+  void makeColours()
   {
     conses[0] = new Consensus("WLVIMAFCYHP", SIXTY);
     conses[1] = new Consensus("WLVIMAFCYHP", EIGHTY);
@@ -167,15 +169,15 @@ public class ClustalxColourScheme extends ResidueColourScheme
 
     Consensus[] tmp8 = new Consensus[1];
     tmp8[0] = conses[30]; // G
-    colours[7] = new ConsensusColour(colhash.get(Color.ORANGE), tmp8);
+    colours[7] = new ConsensusColour(ClustalColour.ORANGE, tmp8);
 
     Consensus[] tmp9 = new Consensus[1];
     tmp9[0] = conses[31]; // P
-    colours[8] = new ConsensusColour(colhash.get(Color.YELLOW), tmp9);
+    colours[8] = new ConsensusColour(ClustalColour.YELLOW, tmp9);
 
     Consensus[] tmp10 = new Consensus[1];
     tmp10[0] = conses[27]; // C
-    colours[9] = new ConsensusColour(colhash.get(Color.PINK), tmp8);
+    colours[9] = new ConsensusColour(ClustalColour.PINK, tmp8);
 
     Consensus[] tmp1 = new Consensus[14];
     tmp1[0] = conses[0]; // %
@@ -192,9 +194,9 @@ public class ClustalxColourScheme extends ResidueColourScheme
     tmp1[11] = conses[25]; // Y
     tmp1[12] = conses[18]; // P
     tmp1[13] = conses[19]; // p
-    colours[0] = new ConsensusColour(colhash.get(Color.BLUE), tmp1);
+    colours[0] = new ConsensusColour(ClustalColour.BLUE, tmp1);
 
-    colours[10] = new ConsensusColour(colhash.get(Color.CYAN), tmp1);
+    colours[10] = new ConsensusColour(ClustalColour.CYAN, tmp1);
 
     Consensus[] tmp2 = new Consensus[5];
     tmp2[0] = conses[8]; // t
@@ -202,14 +204,14 @@ public class ClustalxColourScheme extends ResidueColourScheme
     tmp2[2] = conses[22]; // T
     tmp2[3] = conses[0]; // %
     tmp2[4] = conses[1]; // #
-    colours[1] = new ConsensusColour(colhash.get(Color.GREEN), tmp2);
+    colours[1] = new ConsensusColour(ClustalColour.GREEN, tmp2);
 
     Consensus[] tmp3 = new Consensus[3];
 
     tmp3[0] = conses[17]; // N
     tmp3[1] = conses[29]; // D
     tmp3[2] = conses[5]; // n
-    colours[2] = new ConsensusColour(colhash.get(Color.GREEN), tmp3);
+    colours[2] = new ConsensusColour(ClustalColour.GREEN, tmp3);
 
     Consensus[] tmp4 = new Consensus[6];
     tmp4[0] = conses[6]; // q = QE
@@ -218,14 +220,14 @@ public class ClustalxColourScheme extends ResidueColourScheme
     tmp4[3] = conses[3]; // +
     tmp4[4] = conses[28]; // K
     tmp4[5] = conses[20]; // R
-    colours[3] = new ConsensusColour(colhash.get(Color.GREEN), tmp4);
+    colours[3] = new ConsensusColour(ClustalColour.GREEN, tmp4);
 
     Consensus[] tmp5 = new Consensus[4];
     tmp5[0] = conses[3]; // +
     tmp5[1] = conses[28]; // K
     tmp5[2] = conses[20]; // R
     tmp5[3] = conses[19]; // Q
-    colours[4] = new ConsensusColour(colhash.get(Color.RED), tmp5);
+    colours[4] = new ConsensusColour(ClustalColour.RED, tmp5);
 
     Consensus[] tmp6 = new Consensus[6];
     tmp6[0] = conses[3]; // -
@@ -234,7 +236,7 @@ public class ClustalxColourScheme extends ResidueColourScheme
     tmp6[3] = conses[6]; // QE
     tmp6[4] = conses[19]; // Q
     tmp6[5] = conses[2]; // DE
-    colours[5] = new ConsensusColour(colhash.get(Color.MAGENTA), tmp6);
+    colours[5] = new ConsensusColour(ClustalColour.MAGENTA, tmp6);
 
     Consensus[] tmp7 = new Consensus[5];
     tmp7[0] = conses[3]; // -
@@ -242,7 +244,7 @@ public class ClustalxColourScheme extends ResidueColourScheme
     tmp7[2] = conses[10]; // E
     tmp7[3] = conses[17]; // N
     tmp7[4] = conses[2]; // DE
-    colours[6] = new ConsensusColour(colhash.get(Color.MAGENTA), tmp7);
+    colours[6] = new ConsensusColour(ClustalColour.MAGENTA, tmp7);
 
     // Now attach the ConsensusColours to the residue letters
     residueColour = new ConsensusColour[20];
@@ -275,48 +277,45 @@ public class ClustalxColourScheme extends ResidueColourScheme
   }
 
   @Override
-  public Color findColour(char c, int j, SequenceI seq)
+  protected Color findColour(char c, int j, SequenceI seq)
   {
-    Color currentColour;
-
-    if (cons2.length <= j
-            || (includeGaps && threshold != 0 && !aboveThreshold(c, j)))
+    // TODO why the test for includeGaps here?
+    if (cons2.length <= j || Comparison.isGap(c)
+    /*|| (includeGaps && threshold != 0 && !aboveThreshold(c, j))*/)
     {
       return Color.white;
     }
 
     int i = ResidueProperties.aaIndex[c];
 
-    currentColour = Color.white;
+    Color colour = Color.white;
 
     if (i > 19)
     {
-      return currentColour;
+      return colour;
     }
 
-    for (int k = 0; k < residueColour[i].conses.length; k++)
+    for (int k = 0; k < residueColour[i].cons.length; k++)
     {
-      if (residueColour[i].conses[k].isConserved(cons2, j, size,
+      if (residueColour[i].cons[k].isConserved(cons2, j, size,
               includeGaps))
       {
-        currentColour = residueColour[i].c;
+        colour = residueColour[i].c;
       }
     }
 
     if (i == 4)
     {
+      /*
+       * override to colour C pink if >85% conserved
+       */
       if (conses[27].isConserved(cons2, j, size, includeGaps))
       {
-        currentColour = colhash.get(Color.PINK);
+        colour = ClustalColour.PINK.colour;
       }
     }
 
-    if (conservationColouring)
-    {
-      currentColour = applyConservation(currentColour, j);
-    }
-
-    return currentColour;
+    return colour;
   }
 
   /**
@@ -337,7 +336,7 @@ public class ClustalxColourScheme extends ResidueColourScheme
   }
 
   @Override
-  public ColourSchemeI applyTo(AnnotatedCollectionI sg,
+  public ColourSchemeI getInstance(AnnotatedCollectionI sg,
           Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
   {
     ClustalxColourScheme css = new ClustalxColourScheme(sg,
@@ -345,19 +344,22 @@ public class ClustalxColourScheme extends ResidueColourScheme
     css.includeGaps = includeGaps;
     return css;
   }
-}
 
-class ConsensusColour
-{
-  Consensus[] conses;
-
-  Color c;
+  @Override
+  public boolean isPeptideSpecific()
+  {
+    return true;
+  }
 
-  public ConsensusColour(Color c, Consensus[] conses)
+  @Override
+  public String getSchemeName()
   {
-    this.conses = conses;
+    return JalviewColourScheme.Clustal.toString();
+  }
 
-    // this.list = list;
-    this.c = c;
+  @Override
+  public boolean isSimple()
+  {
+    return false;
   }
 }
index da99a4a..f16ca21 100755 (executable)
@@ -21,7 +21,6 @@
 package jalview.schemes;
 
 import jalview.datamodel.AnnotatedCollectionI;
-import jalview.datamodel.ProfilesI;
 import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceI;
 
@@ -31,99 +30,72 @@ import java.util.Map;
 public interface ColourSchemeI
 {
   /**
+   * Returns the possibly context dependent colour for the given symbol at the
+   * aligned position in the given sequence. For example, the colour may depend
+   * on the symbol's relationship to the consensus residue for the column.
    * 
-   * @param c
-   * @return the colour for the given character
-   */
-  public Color findColour(char c);
-
-  /**
-   * 
-   * @param c
-   *          - sequence symbol or gap
-   * @param j
-   *          - position in seq
+   * @param symbol
+   * @param position
    * @param seq
-   *          - sequence being coloured
-   * @return context dependent colour for the given symbol at the position in
-   *         the given sequence
-   */
-  public Color findColour(char c, int j, SequenceI seq);
-
-  /**
-   * assign the given consensus profile for the colourscheme
-   */
-  public void setConsensus(ProfilesI hconsensus);
-
-  /**
-   * assign the given conservation to the colourscheme
-   * 
-   * @param c
-   */
-  public void setConservation(jalview.analysis.Conservation c);
-
-  /**
-   * enable or disable conservation shading for this colourscheme
-   * 
-   * @param conservationApplied
-   */
-  public void setConservationApplied(boolean conservationApplied);
-
-  /**
-   * 
-   * @return true if conservation shading is enabled for this colourscheme
+   * @param consensusResidue
+   *          the modal symbol (e.g. K) or symbols (e.g. KF) for the column
+   * @param pid
+   *          the percentage identity of the column's consensus (if known)
+   * @return
    */
-  public boolean conservationApplied();
-
-  /**
-   * set scale factor for bleaching of colour in unconserved regions
-   * 
-   * @param i
-   */
-  public void setConservationInc(int i);
+  Color findColour(char symbol, int position, SequenceI seq,
+          String consensusResidue, float pid);
 
   /**
+   * Recalculate dependent data using the given sequence collection, taking
+   * account of hidden rows
    * 
-   * @return scale factor for bleaching colour in unconserved regions
+   * @param alignment
+   * @param hiddenReps
    */
-  public int getConservationInc();
+  void alignmentChanged(AnnotatedCollectionI alignment,
+          Map<SequenceI, SequenceCollectionI> hiddenReps);
 
   /**
+   * Creates and returns a new instance of the colourscheme configured to colour
+   * the given collection. Note that even simple colour schemes should return a
+   * new instance for each call to this method, as different instances may have
+   * differing shading by consensus or percentage identity applied.
    * 
-   * @return percentage identity threshold for applying colourscheme
+   * @param sg
+   * @param hiddenRepSequences
+   * @return copy of current scheme with any inherited settings transferred
    */
-  public int getThreshold();
+  ColourSchemeI getInstance(AnnotatedCollectionI sg,
+          Map<SequenceI, SequenceCollectionI> hiddenRepSequences);
 
   /**
-   * set percentage identity threshold and type of %age identity calculation for
-   * shading
+   * Answers true if the colour scheme is suitable for the given data, else
+   * false. For example, some colour schemes are specific to either peptide or
+   * nucleotide, or only apply if certain kinds of annotation are present.
    * 
-   * @param ct
-   *          0..100 percentage identity for applying this colourscheme
-   * @param ignoreGaps
-   *          when true, calculate PID without including gapped positions
+   * @param ac
+   * @return
    */
-  public void setThreshold(int ct, boolean ignoreGaps);
+  // TODO can make this method static in Java 8
+  boolean isApplicableTo(AnnotatedCollectionI ac);
 
   /**
-   * recalculate dependent data using the given sequence collection, taking
-   * account of hidden rows
+   * Answers the 'official' name of the colour scheme (as used, for example, as
+   * a Jalview startup parameter)
    * 
-   * @param alignment
-   * @param hiddenReps
+   * @return
    */
-  public void alignmentChanged(AnnotatedCollectionI alignment,
-          Map<SequenceI, SequenceCollectionI> hiddenReps);
+  String getSchemeName();
 
   /**
-   * create a new instance of the colourscheme configured to colour the given
-   * connection
+   * Answers true if the colour scheme depends only on the sequence symbol, and
+   * not on other information such as alignment consensus or annotation. (Note
+   * that simple colour schemes may have a fading by percentage identity or
+   * conservation overlaid.) Simple colour schemes can be propagated to
+   * structure viewers.
    * 
-   * @param sg
-   * @param hiddenRepSequences
-   * @return copy of current scheme with any inherited settings transfered
+   * @return
    */
-  public ColourSchemeI applyTo(AnnotatedCollectionI sg,
-          Map<SequenceI, SequenceCollectionI> hiddenRepSequences);
-
+  boolean isSimple();
 }
index 0d9c39d..3e8e87a 100755 (executable)
@@ -21,6 +21,7 @@
 package jalview.schemes;
 
 import jalview.datamodel.AnnotatedCollectionI;
+import jalview.util.ColorUtils;
 
 import java.awt.Color;
 
@@ -38,564 +39,68 @@ import java.awt.Color;
  */
 public class ColourSchemeProperty
 {
-  /** Undefined Colourscheme Index */
-  public static final int UNDEFINED = -1;
-
-  /** for schemes defined on the fly */
-  public static final int USER_DEFINED = 0;
-
-  /** No Colourscheme Index */
-  public static final int NONE = 1;
-
-  /** DOCUMENT ME!! */
-  public static final int CLUSTAL = 2;
-
-  /** DOCUMENT ME!! */
-  public static final int BLOSUM = 3;
-
-  /** DOCUMENT ME!! */
-  public static final int PID = 4;
-
-  /** DOCUMENT ME!! */
-  public static final int ZAPPO = 5;
-
-  /** DOCUMENT ME!! */
-  public static final int TAYLOR = 6;
-
-  /** DOCUMENT ME!! */
-  public static final int HYDROPHOBIC = 7;
-
-  /** DOCUMENT ME!! */
-  public static final int HELIX = 8;
-
-  /** DOCUMENT ME!! */
-  public static final int STRAND = 9;
-
-  /** DOCUMENT ME!! */
-  public static final int TURN = 10;
-
-  /** DOCUMENT ME!! */
-  public static final int BURIED = 11;
-
-  /** DOCUMENT ME!! */
-  public static final int NUCLEOTIDE = 12;
 
   /**
-   * purine/pyrimidine
-   */
-  public static final int PURINEPYRIMIDINE = 13;
-
-  public static final int COVARIATION = 14;
-
-  public static final int TCOFFEE = 15;
-
-  public static final int RNAHELIX = 16;
-
-  public static final int RNAINTERACTION = 17;
-
-  /**
-   * index of first colourscheme (includes 'None')
-   */
-  public static final int FIRST_COLOUR = NONE;
-
-  public static final int LAST_COLOUR = RNAINTERACTION;
-
-  /**
-   * DOCUMENT ME!
+   * Returns a colour scheme for the given name, with which the given data may
+   * be coloured. The name is not case-sensitive, and may be one of
+   * <ul>
+   * <li>any currently registered colour scheme; Jalview by default provides</li>
+   * <ul>
+   * <li>Clustal</li>
+   * <li>Blosum62</li>
+   * <li>% Identity</li>
+   * <li>Hydrophobic</li>
+   * <li>Zappo</li>
+   * <li>Taylor</li>
+   * <li>Helix Propensity</li>
+   * <li>Strand Propensity</li>
+   * <li>Turn Propensity</li>
+   * <li>Buried Index</li>
+   * <li>Nucleotide</li>
+   * <li>Purine/Pyrimidine</li>
+   * <li>T-Coffee Scores</li>
+   * <li>RNA Helices</li>
+   * </ul>
+   * <li>the name of a programmatically added colour scheme</li> <li>an AWT
+   * colour name e.g. red</li> <li>an AWT hex rgb colour e.g. ff2288</li> <li>
+   * residue colours list e.g. D,E=red;K,R,H=0022FF;c=yellow</li> </ul>
    * 
-   * @param name
-   *          DOCUMENT ME!
+   * If none of these formats is matched, the string is converted to a colour
+   * using a hashing algorithm. For name "None", returns null.
    * 
-   * @return DOCUMENT ME!
+   * @param forData
+   * @param name
+   * @return
    */
-  public static int getColourIndexFromName(String name)
+  public static ColourSchemeI getColourScheme(AnnotatedCollectionI forData,
+          String name)
   {
-    int ret = UNDEFINED;
-
-    if (name.equalsIgnoreCase("Clustal"))
+    if (ResidueColourScheme.NONE.equalsIgnoreCase(name))
     {
-      ret = CLUSTAL;
-    }
-    else if (name.equalsIgnoreCase("Blosum62"))
-    {
-      ret = BLOSUM;
-    }
-    else if (name.equalsIgnoreCase("% Identity"))
-    {
-      ret = PID;
-    }
-    else if (name.equalsIgnoreCase("Zappo"))
-    {
-      ret = ZAPPO;
-    }
-    else if (name.equalsIgnoreCase("Taylor"))
-    {
-      ret = TAYLOR;
-    }
-    else if (name.equalsIgnoreCase("Hydrophobic"))
-    {
-      ret = HYDROPHOBIC;
-    }
-    else if (name.equalsIgnoreCase("Helix Propensity"))
-    {
-      ret = HELIX;
-    }
-    else if (name.equalsIgnoreCase("Strand Propensity"))
-    {
-      ret = STRAND;
-    }
-    else if (name.equalsIgnoreCase("Turn Propensity"))
-    {
-      ret = TURN;
-    }
-    else if (name.equalsIgnoreCase("Buried Index"))
-    {
-      ret = BURIED;
-    }
-    else if (name.equalsIgnoreCase("Nucleotide"))
-    {
-      ret = NUCLEOTIDE;
-    }
-    else if (name.equalsIgnoreCase("T-Coffee Scores"))
-    {
-      ret = TCOFFEE;
-    }
+      return null;
 
-    else if (name.equalsIgnoreCase("User Defined"))
-    {
-      ret = USER_DEFINED;
-    }
-    else if (name.equalsIgnoreCase("None"))
-    {
-      ret = NONE;
-    }
-    else if (name.equalsIgnoreCase("Purine/Pyrimidine"))
-    {
-      ret = PURINEPYRIMIDINE;
-    }
-    else if (name.equalsIgnoreCase("RNA Interaction type"))
-    {
-      ret = RNAINTERACTION;
-    }
-    else if (name.equalsIgnoreCase("RNA Helices"))
-    {
-      ret = RNAHELIX;
     }
-    // else if (name.equalsIgnoreCase("Covariation"))
-    // {
-    // ret = COVARIATION;
-    // }
-
-    return ret;
-  }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param cs
-   *          DOCUMENT ME!
-   * 
-   * @return DOCUMENT ME!
-   */
-  public static String getColourName(ColourSchemeI cs)
-  {
-
-    int index = NONE;
-
-    if (cs instanceof ClustalxColourScheme)
-    {
-      index = CLUSTAL;
-    }
-    else if (cs instanceof Blosum62ColourScheme)
-    {
-      index = BLOSUM;
-    }
-    else if (cs instanceof PIDColourScheme)
-    {
-      index = PID;
-    }
-    else if (cs instanceof ZappoColourScheme)
-    {
-      index = ZAPPO;
-    }
-    else if (cs instanceof TaylorColourScheme)
-    {
-      index = TAYLOR;
-    }
-    else if (cs instanceof HydrophobicColourScheme)
-    {
-      index = HYDROPHOBIC;
-    }
-    else if (cs instanceof HelixColourScheme)
-    {
-      index = HELIX;
-    }
-    else if (cs instanceof StrandColourScheme)
-    {
-      index = STRAND;
-    }
-    else if (cs instanceof TurnColourScheme)
-    {
-      index = TURN;
-    }
-    else if (cs instanceof BuriedColourScheme)
-    {
-      index = BURIED;
-    }
-    else if (cs instanceof NucleotideColourScheme)
-    {
-      index = NUCLEOTIDE;
-    }
-    else if (cs instanceof PurinePyrimidineColourScheme)
-    {
-      index = PURINEPYRIMIDINE;
-    }
-    else if (cs instanceof TCoffeeColourScheme)
-    {
-      index = TCOFFEE;
-    }
-    else if (cs instanceof RNAHelicesColour)
-    {
-      index = RNAHELIX;
-    }
     /*
-     * else if (cs instanceof CovariationColourScheme) { index = COVARIATION; }
+     * if this is the name of a registered colour scheme, just
+     * create a new instance of it
      */
-    else if (cs instanceof UserColourScheme)
+    ColourSchemeI scheme = ColourSchemes.getInstance().getColourScheme(
+            name, forData, null);
+    if (scheme != null)
     {
-      if ((((UserColourScheme) cs).getName() != null)
-              && (((UserColourScheme) cs).getName().length() > 0))
-      {
-        return ((UserColourScheme) cs).getName();
-      }
-      // get default colourscheme name
-      index = USER_DEFINED;
+      return scheme;
     }
 
-    return getColourName(index);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param index
-   *          DOCUMENT ME!
-   * 
-   * @return DOCUMENT ME!
-   */
-  public static String getColourName(int index)
-  {
-    String ret = null;
-
-    switch (index)
-    {
-    case CLUSTAL:
-      ret = "Clustal";
-
-      break;
-
-    case BLOSUM:
-      ret = "Blosum62";
-
-      break;
-
-    case PID:
-      ret = "% Identity";
-
-      break;
-
-    case ZAPPO:
-      ret = "Zappo";
-
-      break;
-
-    case TAYLOR:
-      ret = "Taylor";
-      break;
-
-    case HYDROPHOBIC:
-      ret = "Hydrophobic";
-
-      break;
-
-    case HELIX:
-      ret = "Helix Propensity";
-
-      break;
-
-    case STRAND:
-      ret = "Strand Propensity";
-
-      break;
-
-    case TURN:
-      ret = "Turn Propensity";
-
-      break;
-
-    case BURIED:
-      ret = "Buried Index";
-
-      break;
-
-    case NUCLEOTIDE:
-      ret = "Nucleotide";
-
-      break;
-
-    case PURINEPYRIMIDINE:
-      ret = "Purine/Pyrimidine";
-
-      break;
-
-    case TCOFFEE:
-      ret = "T-Coffee Scores";
-
-      break;
-
-    case RNAINTERACTION:
-      ret = "RNA Interaction type";
-
-      break;
-    case RNAHELIX:
-      ret = "RNA Helices";
-
-      break;
     /*
-     * case COVARIATION: ret = "Covariation";
-     * 
-     * break;
+     * try to parse the string as a residues colour scheme
+     * e.g. A=red;T,G=blue etc
+     * else parse the name as a colour specification
+     * e.g. "red" or "ff00ed",
+     * or failing that hash the name to a colour
      */
-    case USER_DEFINED:
-      ret = "User Defined";
-
-      break;
-
-    default:
-      ret = "None";
-
-      break;
-    }
-
-    return ret;
-  }
-
-  /**
-   * retrieve or create colourscheme associated with name
-   * 
-   * @param seqs
-   *          sequences to colour
-   * @param width
-   *          range of sequences to colour
-   * @param name
-   *          colourscheme name, applet colour parameter specification, or
-   *          string to parse as colour for new coloursheme
-   * @return Valid Colourscheme
-   */
-  public static ColourSchemeI getColour(AnnotatedCollectionI alignment,
-          String name)
-  {
-    int colindex = getColourIndexFromName(name);
-    if (colindex == UNDEFINED)
-    {
-      if (name.indexOf('=') == -1)
-      {
-        // try to build a colour from the string directly
-        try
-        {
-          return new UserColourScheme(name);
-        } catch (Exception e)
-        {
-          // System.err.println("Ignoring unknown colourscheme name");
-        }
-      }
-      else
-      {
-        // try to parse the string as a residue colourscheme
-        try
-        {
-          // fix the launchApp user defined coloursheme transfer bug
-          jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
-                  "white");
-          ucs.parseAppletParameter(name);
-
-        } catch (Exception e)
-        {
-          // System.err.println("Ignoring exception when parsing colourscheme as applet-parameter");
-        }
-      }
-    }
-    return getColour(alignment, getColourIndexFromName(name));
-  }
-
-  /**
-   * Construct an instance of ColourSchemeI corresponding to the given
-   * colourscheme index
-   * 
-   * @param seqs
-   *          sequences to be coloured by colourscheme
-   * @param width
-   *          geometry of alignment
-   * @param index
-   *          colourscheme number
-   * 
-   * @return null or an instance of the colourscheme configured to colour given
-   *         sequence set
-   */
-  public static ColourSchemeI getColour(
-          jalview.datamodel.AnnotatedCollectionI coll, int index)
-  {
-    // TODO 3.0 2.8 refactor signature to take an alignmentI like container so
-    // colourschemes based on annotation can be initialised
-    ColourSchemeI cs = null;
-
-    switch (index)
-    {
-    case CLUSTAL:
-      cs = new ClustalxColourScheme(coll, null);
-
-      break;
-
-    case BLOSUM:
-      cs = new Blosum62ColourScheme();
-
-      break;
-
-    case PID:
-      cs = new PIDColourScheme();
-
-      break;
-
-    case ZAPPO:
-      cs = new ZappoColourScheme();
-
-      break;
-
-    case TAYLOR:
-      cs = new TaylorColourScheme();
-      break;
-
-    case HYDROPHOBIC:
-      cs = new HydrophobicColourScheme();
-
-      break;
-
-    case HELIX:
-      cs = new HelixColourScheme();
-
-      break;
-
-    case STRAND:
-      cs = new StrandColourScheme();
-
-      break;
-
-    case TURN:
-      cs = new TurnColourScheme();
-
-      break;
-
-    case BURIED:
-      cs = new BuriedColourScheme();
-
-      break;
-
-    case NUCLEOTIDE:
-      cs = new NucleotideColourScheme();
-
-      break;
-
-    case PURINEPYRIMIDINE:
-      cs = new PurinePyrimidineColourScheme();
-
-      break;
-
-    case TCOFFEE:
-      cs = new TCoffeeColourScheme(coll);
-      break;
-
-    case RNAHELIX:
-      cs = new RNAHelicesColour(coll);
-      break;
-
-    // case COVARIATION:
-    // cs = new CovariationColourScheme(annotation);
-    // break;
-
-    case USER_DEFINED:
-      Color[] col = new Color[24];
-      for (int i = 0; i < 24; i++)
-      {
-        col[i] = Color.white;
-      }
-      cs = new UserColourScheme(col);
-      break;
-
-    default:
-      break;
-    }
-
-    return cs;
-  }
-
-  public static Color getAWTColorFromName(String name)
-  {
-    Color col = null;
-    name = name.toLowerCase();
-    if (name.equals("black"))
-    {
-      col = Color.black;
-    }
-    else if (name.equals("blue"))
-    {
-      col = Color.blue;
-    }
-    else if (name.equals("cyan"))
-    {
-      col = Color.cyan;
-    }
-    else if (name.equals("darkGray"))
-    {
-      col = Color.darkGray;
-    }
-    else if (name.equals("gray"))
-    {
-      col = Color.gray;
-    }
-    else if (name.equals("green"))
-    {
-      col = Color.green;
-    }
-    else if (name.equals("lightGray"))
-    {
-      col = Color.lightGray;
-    }
-    else if (name.equals("magenta"))
-    {
-      col = Color.magenta;
-    }
-    else if (name.equals("orange"))
-    {
-      col = Color.orange;
-    }
-    else if (name.equals("pink"))
-    {
-      col = Color.pink;
-    }
-    else if (name.equals("red"))
-    {
-      col = Color.red;
-    }
-    else if (name.equals("white"))
-    {
-      col = Color.white;
-    }
-    else if (name.equals("yellow"))
-    {
-      col = Color.yellow;
-    }
-
-    return col;
+    UserColourScheme ucs = new UserColourScheme(name);
+    return ucs;
   }
 
   public static Color rnaHelices[] = null;
@@ -621,17 +126,28 @@ public class ColourSchemeProperty
     // Generate random colors and store
     for (; j <= n; j++)
     {
-      rnaHelices[j] = jalview.util.ColorUtils
-              .generateRandomColor(Color.white);
+      rnaHelices[j] = ColorUtils.generateRandomColor(Color.white);
     }
   }
 
   /**
-   * delete the existing cached RNA helces colours
+   * delete the existing cached RNA helices colours
    */
   public static void resetRnaHelicesShading()
   {
     rnaHelices = null;
   }
 
+  /**
+   * Returns the name of the colour scheme (or "None" if it is null)
+   * 
+   * @param cs
+   * @return
+   */
+  public static String getColourName(ColourSchemeI cs)
+  {
+    return cs == null ? ResidueColourScheme.NONE : cs
+            .getSchemeName();
+  }
+
 }
diff --git a/src/jalview/schemes/ColourSchemes.java b/src/jalview/schemes/ColourSchemes.java
new file mode 100644 (file)
index 0000000..817fb01
--- /dev/null
@@ -0,0 +1,290 @@
+package jalview.schemes;
+
+import jalview.binding.JalviewUserColours;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+
+import java.awt.Color;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class ColourSchemes
+{
+  /*
+   * singleton instance of this class
+   */
+  private static ColourSchemes instance = new ColourSchemes();
+
+  /*
+   * a map from scheme name to an instance of it
+   */
+  private Map<String, ColourSchemeI> schemes;
+
+  /**
+   * Returns the singleton instance of this class
+   * 
+   * @return
+   */
+  public static ColourSchemes getInstance()
+  {
+    return instance;
+  }
+
+  private ColourSchemes()
+  {
+    loadColourSchemes();
+  }
+
+  /**
+   * Loads an instance of each standard or user-defined colour scheme
+   * 
+   * @return
+   */
+  void loadColourSchemes()
+  {
+    /*
+     * store in an order-preserving map, so items can be added to menus 
+     * in the order in which they are 'discovered'
+     */
+    schemes = new LinkedHashMap<String, ColourSchemeI>();
+
+    for (JalviewColourScheme cs : JalviewColourScheme.values())
+    {
+      try
+      {
+        registerColourScheme(cs.getSchemeClass().newInstance());
+      } catch (InstantiationException | IllegalAccessException e)
+      {
+        System.err.println("Error instantiating colour scheme for "
+                + cs.toString() + " " + e.getMessage());
+      }
+    }
+  }
+
+  /**
+   * Registers a colour scheme
+   * 
+   * @param cs
+   */
+  public void registerColourScheme(ColourSchemeI cs)
+  {
+    String name = cs.getSchemeName();
+    if (name == null)
+    {
+      System.err.println("ColourScheme name may not be null");
+      return;
+    }
+
+    /*
+     * name is lower-case for non-case-sensitive lookup
+     * (name in the colour keeps its true case)
+     */
+    String lower = name.toLowerCase();
+    if (schemes.containsKey(lower))
+    {
+      System.err
+              .println("Warning: overwriting colour scheme named " + name);
+    }
+    schemes.put(lower, cs);
+  }
+
+  /**
+   * Removes a colour scheme by name
+   * 
+   * @param name
+   */
+  public void removeColourScheme(String name)
+  {
+    schemes.remove(name);
+  }
+  
+  /**
+   * Returns an instance of the colour scheme with which the given view may be
+   * coloured
+   * 
+   * @param name
+   *          name of the colour scheme
+   * @param forData
+   *          the data to be coloured
+   * @param optional
+   *          map from hidden representative sequences to the sequences they
+   *          represent
+   * @return
+   */
+  public ColourSchemeI getColourScheme(String name,
+          AnnotatedCollectionI forData,
+          Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
+  {
+    if (name == null)
+    {
+      return null;
+    }
+    ColourSchemeI cs = schemes.get(name.toLowerCase());
+    return cs == null ? null : cs.getInstance(forData, hiddenRepSequences);
+  }
+
+  /**
+   * Returns an instance of the colour scheme with which the given view may be
+   * coloured
+   * 
+   * @param name
+   *          name of the colour scheme
+   * @param forData
+   *          the data to be coloured
+   * @return
+   */
+  public ColourSchemeI getColourScheme(String name,
+          AnnotatedCollectionI forData)
+  {
+    return getColourScheme(name, forData, null);
+  }
+
+  /**
+   * Returns an iterable set of the colour schemes, in the order in which they
+   * were added
+   * 
+   * @return
+   */
+  public Iterable<ColourSchemeI> getColourSchemes()
+  {
+    return schemes.values();
+  }
+
+  /**
+   * Answers true if there is a scheme with the given name, else false. The test
+   * is not case-sensitive.
+   * 
+   * @param name
+   * @return
+   */
+  public boolean nameExists(String name)
+  {
+    if (name == null)
+    {
+      return false;
+    }
+    name = name.toLowerCase();
+    for (ColourSchemeI scheme : getColourSchemes())
+    {
+      if (name.equals(scheme.getSchemeName().toLowerCase()))
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Loads a user defined colour scheme from file. The file should contain a
+   * definition of residue colours in XML format as defined in
+   * JalviewUserColours.xsd.
+   * 
+   * @param filePath
+   * 
+   * @return
+   */
+  public static UserColourScheme loadColourScheme(String filePath)
+  {
+    UserColourScheme ucs = null;
+    Color[] newColours = null;
+    File file = new File(filePath);
+    try
+    {
+      InputStreamReader in = new InputStreamReader(
+              new FileInputStream(file), "UTF-8");
+  
+      jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
+  
+      org.exolab.castor.xml.Unmarshaller unmar = new org.exolab.castor.xml.Unmarshaller(
+              jucs);
+      jucs = (jalview.schemabinding.version2.JalviewUserColours) unmar
+              .unmarshal(in);
+  
+      /*
+       * non-case-sensitive colours are for 20 amino acid codes,
+       * B, Z, X and Gap
+       * optionally, lower-case alternatives for all except Gap
+       */
+      newColours = new Color[24];
+      Color[] lowerCase = new Color[23];
+      boolean caseSensitive = false;
+  
+      String name;
+      int index;
+      for (int i = 0; i < jucs.getColourCount(); i++)
+      {
+        name = jucs.getColour(i).getName();
+        if (ResidueProperties.aa3Hash.containsKey(name))
+        {
+          index = ResidueProperties.aa3Hash.get(name).intValue();
+        }
+        else
+        {
+          index = ResidueProperties.aaIndex[name.charAt(0)];
+        }
+        if (index == -1)
+        {
+          continue;
+        }
+  
+        Color color = new Color(Integer.parseInt(jucs.getColour(i)
+                .getRGB(), 16));
+        if (name.toLowerCase().equals(name))
+        {
+          caseSensitive = true;
+          lowerCase[index] = color;
+        }
+        else
+        {
+          newColours[index] = color;
+        }
+      }
+  
+      /*
+       * instantiate the colour scheme
+       */
+      ucs = new UserColourScheme(newColours);
+      ucs.setName(jucs.getSchemeName());
+      if (caseSensitive)
+      {
+        ucs.setLowerCaseColours(lowerCase);
+      }
+    } catch (Exception ex)
+    {
+      // Could be old Jalview Archive format
+      try
+      {
+        InputStreamReader in = new InputStreamReader(new FileInputStream(
+                file), "UTF-8");
+  
+        jalview.binding.JalviewUserColours jucs = new jalview.binding.JalviewUserColours();
+  
+        jucs = JalviewUserColours.unmarshal(in);
+  
+        newColours = new Color[jucs.getColourCount()];
+  
+        for (int i = 0; i < 24; i++)
+        {
+          newColours[i] = new Color(Integer.parseInt(jucs.getColour(i)
+                  .getRGB(), 16));
+        }
+        ucs = new UserColourScheme(newColours);
+        ucs.setName(jucs.getSchemeName());
+      } catch (Exception ex2)
+      {
+        ex2.printStackTrace();
+      }
+  
+      if (newColours == null)
+      {
+        System.out.println("Error loading User ColourFile\n" + ex);
+      }
+    }
+  
+    return ucs;
+  }
+}
index 49d5dee..6cb095b 100644 (file)
 package jalview.schemes;
 
 import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+import jalview.util.ColorUtils;
 
 import java.awt.Color;
 import java.util.Hashtable;
+import java.util.Map;
 
 /**
  * Became RNAHelicesColour.java. Placeholder for true covariation color scheme
@@ -33,15 +38,26 @@ import java.util.Hashtable;
  */
 public class CovariationColourScheme extends ResidueColourScheme
 {
-  public Hashtable helixcolorhash = new Hashtable();
+  public Map<String, Color> helixcolorhash = new Hashtable<String, Color>();
 
-  public Hashtable positionsToHelix = new Hashtable();
+  public Map<Integer, String> positionsToHelix = new Hashtable<Integer, String>();
 
   int numHelix = 0;
 
   public AlignmentAnnotation annotation;
 
   /**
+   * Returns a new instance of this colour scheme with which the given data may
+   * be coloured
+   */
+  @Override
+  public ColourSchemeI getInstance(AnnotatedCollectionI coll,
+          Map<SequenceI, SequenceCollectionI> hrs)
+  {
+    return new CovariationColourScheme(coll.getAlignmentAnnotation()[0]);
+  }
+
+  /**
    * Creates a new CovariationColourScheme object.
    */
   public CovariationColourScheme(AlignmentAnnotation annotation)
@@ -71,8 +87,8 @@ public class CovariationColourScheme extends ResidueColourScheme
 
     for (int j = 0; j <= numHelix; j++)
     {
-      helixcolorhash.put(Integer.toString(j),
-              jalview.util.ColorUtils.generateRandomColor(Color.white));
+      helixcolorhash.put(String.valueOf(j),
+              ColorUtils.generateRandomColor(Color.white));
     }
 
   }
@@ -85,6 +101,7 @@ public class CovariationColourScheme extends ResidueColourScheme
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public Color findColour(char c)
   {
     // System.out.println("called"); log.debug
@@ -108,12 +125,12 @@ public class CovariationColourScheme extends ResidueColourScheme
     Color currentColour = Color.white;
     String currentHelix = null;
     // System.out.println(c + " " + j);
-    currentHelix = (String) positionsToHelix.get(j);
+    currentHelix = positionsToHelix.get(j);
     // System.out.println(positionsToHelix.get(j));
 
     if (currentHelix != null)
     {
-      currentColour = (Color) helixcolorhash.get(currentHelix);
+      currentColour = helixcolorhash.get(currentHelix);
     }
 
     // System.out.println(c + " " + j + " helix " + currentHelix + " " +
@@ -121,4 +138,21 @@ public class CovariationColourScheme extends ResidueColourScheme
     return currentColour;
   }
 
+  @Override
+  public boolean isNucleotideSpecific()
+  {
+    return true;
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return "Covariation";
+  }
+
+  @Override
+  public boolean isSimple()
+  {
+    return false;
+  }
 }
index 23087a8..dbe4901 100644 (file)
@@ -22,6 +22,7 @@ package jalview.schemes;
 
 import jalview.api.FeatureColourI;
 import jalview.datamodel.SequenceFeature;
+import jalview.util.ColorUtils;
 import jalview.util.Format;
 
 import java.awt.Color;
@@ -121,7 +122,7 @@ public class FeatureColour implements FeatureColourI
       /*
        * only a simple colour specification - parse it
        */
-      Color colour = UserColourScheme.getColourFromString(descriptor);
+      Color colour = ColorUtils.parseColourString(descriptor);
       if (colour == null)
       {
         throw new IllegalArgumentException("Invalid colour descriptor: "
@@ -212,9 +213,9 @@ public class FeatureColour implements FeatureColourI
     FeatureColour featureColour;
     try
     {
-      featureColour = new FeatureColour(
-              new UserColourScheme(mincol).findColour('A'),
-              new UserColourScheme(maxcol).findColour('A'), min, max);
+      Color minColour = ColorUtils.parseColourString(mincol);
+      Color maxColour = ColorUtils.parseColourString(maxcol);
+      featureColour = new FeatureColour(minColour, maxColour, min, max);
       featureColour.setColourByLabel(labelColour);
       featureColour.setAutoScaled(autoScaled);
       // add in any additional parameters
@@ -306,6 +307,14 @@ public class FeatureColour implements FeatureColourI
    */
   public FeatureColour(Color low, Color high, float min, float max)
   {
+    if (low == null)
+    {
+      low = Color.white;
+    }
+    if (high == null)
+    {
+      high = Color.black;
+    }
     graduatedColour = true;
     colour = null;
     minColour = low;
@@ -533,7 +542,7 @@ public class FeatureColour implements FeatureColourI
   {
     if (isColourByLabel())
     {
-      return UserColourScheme
+      return ColorUtils
               .createColourFromName(feature.getDescription());
     }
 
index 35be31b..57c19e5 100644 (file)
  */
 package jalview.schemes;
 
-import jalview.analysis.Conservation;
-import jalview.datamodel.ProfilesI;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+
+import java.util.Map;
 
 /**
  * Colourscheme that takes its colours from some other colourscheme
@@ -32,7 +35,7 @@ import jalview.datamodel.ProfilesI;
 public class FollowerColourScheme extends ResidueColourScheme
 {
 
-  protected ColourSchemeI colourScheme;
+  private ColourSchemeI colourScheme;
 
   public ColourSchemeI getBaseColour()
   {
@@ -40,30 +43,30 @@ public class FollowerColourScheme extends ResidueColourScheme
   }
 
   @Override
-  public void setConsensus(ProfilesI consensus)
+  public String getSchemeName()
   {
-    if (colourScheme != null)
-    {
-      colourScheme.setConsensus(consensus);
-    }
+    return "Follower";
   }
 
+  /**
+   * Returns a new instance of this colour scheme with which the given data may
+   * be coloured
+   */
   @Override
-  public void setConservation(Conservation cons)
+  public ColourSchemeI getInstance(AnnotatedCollectionI coll,
+          Map<SequenceI, SequenceCollectionI> hrs)
   {
-    if (colourScheme != null)
-    {
-      colourScheme.setConservation(cons);
-    }
+    return new FollowerColourScheme();
   }
 
-  @Override
-  public void setConservationInc(int i)
+  protected ColourSchemeI getColourScheme()
+  {
+    return colourScheme;
+  }
+
+  protected void setColourScheme(ColourSchemeI colourScheme)
   {
-    if (colourScheme != null)
-    {
-      colourScheme.setConservationInc(i);
-    }
+    this.colourScheme = colourScheme;
   }
 
 }
index 1242cd3..7123d93 100755 (executable)
  */
 package jalview.schemes;
 
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+
 import java.awt.Color;
+import java.util.Map;
 
 public class HelixColourScheme extends ScoreColourScheme
 {
@@ -30,8 +35,32 @@ public class HelixColourScheme extends ScoreColourScheme
             ResidueProperties.helixmin, ResidueProperties.helixmax);
   }
 
+  @Override
   public Color makeColour(float c)
   {
     return new Color(c, (float) 1.0 - c, c);
   }
+
+  @Override
+  public boolean isPeptideSpecific()
+  {
+    return true;
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return JalviewColourScheme.Helix.toString();
+  }
+
+  /**
+   * Returns a new instance of this colour scheme with which the given data may
+   * be coloured
+   */
+  @Override
+  public ColourSchemeI getInstance(AnnotatedCollectionI coll,
+          Map<SequenceI, SequenceCollectionI> hrs)
+  {
+    return new HelixColourScheme();
+  }
 }
index 055000f..69af3c9 100755 (executable)
  */
 package jalview.schemes;
 
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+
 import java.awt.Color;
+import java.util.Map;
 
 /**
  * DOCUMENT ME!
@@ -47,8 +52,32 @@ public class HydrophobicColourScheme extends ScoreColourScheme
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public Color makeColour(float c)
   {
     return new Color(c, (float) 0.0, (float) 1.0 - c);
   }
+
+  @Override
+  public boolean isPeptideSpecific()
+  {
+    return true;
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return JalviewColourScheme.Hydrophobic.toString();
+  }
+
+  /**
+   * Returns a new instance of this colour scheme with which the given data may
+   * be coloured
+   */
+  @Override
+  public ColourSchemeI getInstance(AnnotatedCollectionI coll,
+          Map<SequenceI, SequenceCollectionI> hrs)
+  {
+    return new HydrophobicColourScheme();
+  }
 }
diff --git a/src/jalview/schemes/JalviewColourScheme.java b/src/jalview/schemes/JalviewColourScheme.java
new file mode 100644 (file)
index 0000000..185d2b4
--- /dev/null
@@ -0,0 +1,66 @@
+package jalview.schemes;
+
+
+/**
+ * An enum with the colour schemes supported by Jalview.
+ */
+public enum JalviewColourScheme
+{
+  /*
+   * the order of declaration is the default order in which 
+   * items are added to Colour menus
+   */
+  Clustal("Clustal", ClustalxColourScheme.class), Blosum62("Blosum62",
+          Blosum62ColourScheme.class), PID("% Identity",
+          PIDColourScheme.class), Zappo("Zappo", ZappoColourScheme.class),
+  Taylor("Taylor", TaylorColourScheme.class), Hydrophobic("Hydrophobic",
+          HydrophobicColourScheme.class), Helix("Helix Propensity",
+          HelixColourScheme.class), Strand("Strand Propensity",
+          StrandColourScheme.class), Turn("Turn Propensity",
+          TurnColourScheme.class), Buried("Buried Index",
+          BuriedColourScheme.class), Nucleotide("Nucleotide",
+          NucleotideColourScheme.class), PurinePyrimidine(
+          "Purine/Pyrimidine", PurinePyrimidineColourScheme.class),
+  RNAHelices("RNA Helices", RNAHelicesColour.class), TCoffee(
+          "T-Coffee Scores", TCoffeeColourScheme.class);
+  // RNAInteraction("RNA Interaction type", RNAInteractionColourScheme.class)
+
+  private String name;
+
+  private Class<? extends ColourSchemeI> myClass;
+
+  /**
+   * Constructor given the name of the colour scheme (as used in Jalview
+   * parameters). Note this is not necessarily the same as the 'display name'
+   * used in menu options (as this may be language-dependent).
+   * 
+   * @param s
+   */
+  JalviewColourScheme(String s, Class<? extends ColourSchemeI> cl)
+  {
+    name = s;
+    myClass = cl;
+  }
+
+  /**
+   * Returns the class of the colour scheme
+   * 
+   * @return
+   */
+  public Class<? extends ColourSchemeI> getSchemeClass()
+  {
+    return myClass;
+  }
+
+  /**
+   * Returns the 'official' name of this colour scheme. This is the name that
+   * identifies the colour scheme as a start-up parameter for the Jalview
+   * application or applet. Note that it may not be the name shown in menu
+   * options, as these may be internationalised.
+   */
+  @Override
+  public String toString()
+  {
+    return name;
+  }
+}
index dff2bf3..abae733 100755 (executable)
  */
 package jalview.schemes;
 
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceI;
 
-import java.awt.Color;
+import java.util.Map;
 
 /**
  * DOCUMENT ME!
@@ -37,59 +39,29 @@ public class NucleotideColourScheme extends ResidueColourScheme
    */
   public NucleotideColourScheme()
   {
-    super(ResidueProperties.nucleotideIndex, ResidueProperties.nucleotide,
-            0);
+    super(ResidueProperties.nucleotideIndex, ResidueProperties.nucleotide);
+  }
+
+  @Override
+  public boolean isNucleotideSpecific()
+  {
+    return true;
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param n
-   *          DOCUMENT ME!
-   * 
-   * @return DOCUMENT ME!
-   */
   @Override
-  public Color findColour(char c)
+  public String getSchemeName()
   {
-    // System.out.println("called"); log.debug
-    return colors[ResidueProperties.nucleotideIndex[c]];
+    return JalviewColourScheme.Nucleotide.toString();
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param n
-   *          DOCUMENT ME!
-   * @param j
-   *          DOCUMENT ME!
-   * 
-   * @return DOCUMENT ME!
+   * Returns a new instance of this colour scheme with which the given data may
+   * be coloured
    */
   @Override
-  public Color findColour(char c, int j, SequenceI seq)
+  public ColourSchemeI getInstance(AnnotatedCollectionI coll,
+          Map<SequenceI, SequenceCollectionI> hrs)
   {
-    Color currentColour;
-    if ((threshold == 0) || aboveThreshold(c, j))
-    {
-      try
-      {
-        currentColour = colors[ResidueProperties.nucleotideIndex[c]];
-      } catch (Exception ex)
-      {
-        return Color.white;
-      }
-    }
-    else
-    {
-      return Color.white;
-    }
-
-    if (conservationColouring)
-    {
-      currentColour = applyConservation(currentColour, j);
-    }
-
-    return currentColour;
+    return new NucleotideColourScheme();
   }
 }
index 0ad5b5c..657d6b0 100755 (executable)
  */
 package jalview.schemes;
 
-import jalview.datamodel.ProfileI;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.util.Comparison;
 
 import java.awt.Color;
+import java.util.Map;
 
 public class PIDColourScheme extends ResidueColourScheme
 {
-  public Color[] pidColours;
+  private static final Color[] pidColours = { new Color(100, 100, 255),
+      new Color(153, 153, 255), new Color(204, 204, 255), };
 
-  public float[] thresholds;
+  private static final float[] thresholds = { 80, 60, 40, };
 
   SequenceGroup group;
 
   public PIDColourScheme()
   {
-    this.pidColours = ResidueProperties.pidColours;
-    this.thresholds = ResidueProperties.pidThresholds;
   }
 
   @Override
-  public Color findColour(char c, int j, SequenceI seq)
+  public Color findColour(char c, int j, SequenceI seq,
+          String consensusResidue, float pid)
   {
+    /*
+     * compare as upper case; note consensusResidue is 
+     * always computed as uppercase
+     */
     if ('a' <= c && c <= 'z')
     {
       c -= ('a' - 'A');
     }
 
-    if (consensus == null || consensus.get(j) == null)
-    {
-      return Color.white;
-    }
-
-    if ((threshold != 0) && !aboveThreshold(c, j))
+    if (consensusResidue == null || Comparison.isGap(c))
     {
       return Color.white;
     }
 
-    Color currentColour = Color.white;
-
-    double sc = 0;
-
+    Color colour = Color.white;
 
     /*
      * test whether this is the consensus (or joint consensus) residue
      */
-    ProfileI profile = consensus.get(j);
-    boolean matchesConsensus = profile.getModalResidue().contains(
+    boolean matchesConsensus = consensusResidue.contains(
             String.valueOf(c));
     if (matchesConsensus)
     {
-      sc = profile.getPercentageIdentity(ignoreGaps);
-
-      if (!Comparison.isGap(c))
+      for (int i = 0; i < thresholds.length; i++)
       {
-        for (int i = 0; i < thresholds.length; i++)
+        if (pid > thresholds[i])
         {
-          if (sc > thresholds[i])
-          {
-            currentColour = pidColours[i];
-            break;
-          }
+          colour = pidColours[i];
+          break;
         }
       }
     }
 
-    if (conservationColouring)
-    {
-      currentColour = applyConservation(currentColour, j);
-    }
+    return colour;
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return JalviewColourScheme.PID.toString();
+  }
 
-    return currentColour;
+  /**
+   * Returns a new instance of this colour scheme with which the given data may
+   * be coloured
+   */
+  @Override
+  public ColourSchemeI getInstance(AnnotatedCollectionI coll,
+          Map<SequenceI, SequenceCollectionI> hrs)
+  {
+    return new PIDColourScheme();
+  }
+
+  @Override
+  public boolean isSimple()
+  {
+    return false;
   }
 }
index d2b878d..1b36f30 100644 (file)
  */
 package jalview.schemes;
 
-import java.awt.Color;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+
+import java.util.Map;
 
 /**
  * Class is based off of NucleotideColourScheme
@@ -35,56 +39,29 @@ public class PurinePyrimidineColourScheme extends ResidueColourScheme
   public PurinePyrimidineColourScheme()
   {
     super(ResidueProperties.purinepyrimidineIndex,
-            ResidueProperties.purinepyrimidine, 0);
+            ResidueProperties.purinepyrimidine);
   }
 
-  /**
-   * Finds the corresponding color for the type of character inputed
-   * 
-   * @param c
-   *          Character in sequence
-   * 
-   * @return Color from purinepyrimidineIndex in
-   *         jalview.schemes.ResidueProperties
-   */
-  public Color findColour(char c)
+  @Override
+  public boolean isNucleotideSpecific()
+  {
+    return true;
+  }
+
+  @Override
+  public String getSchemeName()
   {
-    return colors[ResidueProperties.purinepyrimidineIndex[c]];
+    return JalviewColourScheme.PurinePyrimidine.toString();
   }
 
   /**
-   * Returns color based on conservation
-   * 
-   * @param c
-   *          Character in sequence
-   * @param j
-   *          Threshold
-   * 
-   * @return Color in RGB
+   * Returns a new instance of this colour scheme with which the given data may
+   * be coloured
    */
-  public Color findColour(char c, int j)
+  @Override
+  public ColourSchemeI getInstance(AnnotatedCollectionI coll,
+          Map<SequenceI, SequenceCollectionI> hrs)
   {
-    Color currentColour;
-    if ((threshold == 0) || aboveThreshold(c, j))
-    {
-      try
-      {
-        currentColour = colors[ResidueProperties.purinepyrimidineIndex[c]];
-      } catch (Exception ex)
-      {
-        return Color.white;
-      }
-    }
-    else
-    {
-      return Color.white;
-    }
-
-    if (conservationColouring)
-    {
-      currentColour = applyConservation(currentColour, j);
-    }
-
-    return currentColour;
+    return new PurinePyrimidineColourScheme();
   }
 }
index 9729a83..056a167 100644 (file)
@@ -21,6 +21,7 @@
 package jalview.schemes;
 
 import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AnnotatedCollectionI;
 import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceI;
@@ -54,6 +55,14 @@ public class RNAHelicesColour extends ResidueColourScheme
   public AlignmentAnnotation annotation;
 
   /**
+   * Default constructor (required for ColourSchemes cache)
+   */
+  public RNAHelicesColour()
+  {
+
+  }
+
+  /**
    * Creates a new RNAHelicesColour object.
    */
   public RNAHelicesColour(AlignmentAnnotation annotation)
@@ -197,9 +206,44 @@ public class RNAHelicesColour extends ResidueColourScheme
   }
 
   @Override
-  public ColourSchemeI applyTo(AnnotatedCollectionI sg,
+  public ColourSchemeI getInstance(AnnotatedCollectionI sg,
           Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
   {
-    return new RNAHelicesColour(this);
+    return new RNAHelicesColour(sg);
+  }
+
+  @Override
+  public boolean isNucleotideSpecific()
+  {
+    return true;
+  }
+
+  /**
+   * Answers true if the data has RNA secondary structure annotation
+   */
+  @Override
+  public boolean isApplicableTo(AnnotatedCollectionI ac)
+  {
+    if (ac instanceof AlignmentI && ((AlignmentI) ac).hasRNAStructure())
+    {
+      return true;
+    }
+
+    /*
+     * not currently supporting this option for group annotation / colouring
+     */
+    return false;
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return JalviewColourScheme.RNAHelices.toString();
+  }
+
+  @Override
+  public boolean isSimple()
+  {
+    return false;
   }
-}
\ No newline at end of file
+}
index b1b3c5a..15cb157 100644 (file)
@@ -25,8 +25,8 @@ import jalview.api.AlignmentViewPanel;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.SequenceGroup;
 
-import java.awt.event.ActionEvent;
 import java.util.Hashtable;
+import java.util.Map;
 import java.util.Vector;
 
 /**
@@ -34,8 +34,9 @@ import java.util.Vector;
  * change colors based on covariation.
  * 
  * @author Lauren Michelle Lui
- * 
+ * @deprecated this seems to be unfinished - just use RNAHelicesColour
  */
+@Deprecated
 public class RNAHelicesColourChooser
 {
 
@@ -45,9 +46,9 @@ public class RNAHelicesColourChooser
 
   ColourSchemeI oldcs;
 
-  Hashtable oldgroupColours;
+  Map<SequenceGroup, ColourSchemeI> oldgroupColours;
 
-  jalview.datamodel.AlignmentAnnotation currentAnnotation;
+  AlignmentAnnotation currentAnnotation;
 
   boolean adjusting = false;
 
@@ -57,26 +58,20 @@ public class RNAHelicesColourChooser
     oldcs = av.getGlobalColourScheme();
     if (av.getAlignment().getGroups() != null)
     {
-      oldgroupColours = new Hashtable();
+      oldgroupColours = new Hashtable<SequenceGroup, ColourSchemeI>();
       for (SequenceGroup sg : ap.getAlignment().getGroups())
       {
-        if (sg.cs != null)
+        if (sg.getColourScheme() != null)
         {
-          oldgroupColours.put(sg, sg.cs);
+          oldgroupColours.put(sg, sg.getColourScheme());
         }
       }
     }
     this.av = av;
     this.ap = ap;
 
-    if (oldcs instanceof RNAHelicesColour)
-    {
-      RNAHelicesColour rhc = (RNAHelicesColour) oldcs;
-
-    }
-
     adjusting = true;
-    Vector list = new Vector();
+    Vector<String> list = new Vector<String>();
     int index = 1;
     AlignmentAnnotation[] anns = av.getAlignment().getAlignmentAnnotation();
     if (anns != null)
@@ -96,9 +91,7 @@ public class RNAHelicesColourChooser
     }
 
     adjusting = false;
-
     changeColour();
-
   }
 
   void changeColour()
@@ -108,30 +101,10 @@ public class RNAHelicesColourChooser
     {
       return;
     }
-    RNAHelicesColour rhc = null;
-
-    rhc = new RNAHelicesColour(av.getAlignment());
+    RNAHelicesColour rhc = new RNAHelicesColour(av.getAlignment());
 
     av.setGlobalColourScheme(rhc);
 
     ap.paintAlignment(true);
   }
-
-  void reset()
-  {
-    av.setGlobalColourScheme(oldcs);
-    if (av.getAlignment().getGroups() != null)
-    {
-      for (SequenceGroup sg : ap.getAlignment().getGroups())
-      {
-        sg.cs = (ColourSchemeI) oldgroupColours.get(sg);
-      }
-    }
-  }
-
-  public void annotations_actionPerformed(ActionEvent e)
-  {
-    changeColour();
-  }
-
 }
index 794195a..d236803 100644 (file)
  */
 package jalview.schemes;
 
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceI;
 
 import java.awt.Color;
+import java.util.Map;
 
 public class RNAInteractionColourScheme extends ResidueColourScheme
 {
@@ -31,55 +34,48 @@ public class RNAInteractionColourScheme extends ResidueColourScheme
     super();
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param n
-   *          DOCUMENT ME!
-   * 
-   * @return DOCUMENT ME!
-   */
   @Override
   public Color findColour(char c)
   {
-    // System.out.println("called"); log.debug
+    // FIXME this is just a copy of NucleotideColourScheme
     return colors[ResidueProperties.nucleotideIndex[c]];
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param n
-   *          DOCUMENT ME!
-   * @param j
-   *          DOCUMENT ME!
-   * 
-   * @return DOCUMENT ME!
-   */
   @Override
   public Color findColour(char c, int j, SequenceI seq)
   {
-    Color currentColour;
-    if ((threshold == 0) || aboveThreshold(c, j))
+    // FIXME this is just a copy of NucleotideColourScheme
+    Color currentColour = Color.white;
+    try
     {
-      try
-      {
-        currentColour = colors[ResidueProperties.nucleotideIndex[c]];
-      } catch (Exception ex)
-      {
-        return Color.white;
-      }
-    }
-    else
+      currentColour = colors[ResidueProperties.nucleotideIndex[c]];
+    } catch (Exception ex)
     {
-      return Color.white;
-    }
-
-    if (conservationColouring)
-    {
-      currentColour = applyConservation(currentColour, j);
     }
 
     return currentColour;
   }
+
+  @Override
+  public boolean isNucleotideSpecific()
+  {
+    return true;
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return "RNA Interaction type";
+  }
+
+  /**
+   * Returns a new instance of this colour scheme with which the given data may
+   * be coloured
+   */
+  @Override
+  public ColourSchemeI getInstance(AnnotatedCollectionI coll,
+          Map<SequenceI, SequenceCollectionI> hrs)
+  {
+    return new RNAInteractionColourScheme();
+  }
 }
index f6b7c5e..03fc129 100755 (executable)
  */
 package jalview.schemes;
 
-import jalview.analysis.Conservation;
 import jalview.datamodel.AnnotatedCollectionI;
-import jalview.datamodel.ProfileI;
-import jalview.datamodel.ProfilesI;
 import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
-import jalview.util.ColorUtils;
 import jalview.util.Comparison;
-import jalview.util.MessageManager;
 
 import java.awt.Color;
 import java.util.Map;
 
 /**
- * DOCUMENT ME!
- * 
- * @author $author$
- * @version $Revision$
+ * Base class for residue-based colour schemes
  */
-public class ResidueColourScheme implements ColourSchemeI
+public abstract class ResidueColourScheme implements ColourSchemeI
 {
-  final int[] symbolIndex;
+  public static final String NONE = "None";
 
-  boolean conservationColouring = false;
-
-  Color[] colors = null;
-
-  int threshold = 0;
-
-  /* Set when threshold colouring to either pid_gaps or pid_nogaps */
-  protected boolean ignoreGaps = false;
+  public static final String USER_DEFINED = "User Defined";
 
   /*
-   * Consensus data indexed by column
+   * lookup up by character value e.g. 'G' to the colors array index
+   * e.g. if symbolIndex['K'] = 11 then colors[11] is the colour for K
    */
-  ProfilesI consensus;
+  final int[] symbolIndex;
 
   /*
-   * Conservation string as a char array 
+   * colour for residue characters as indexed by symbolIndex
    */
-  char[] conservation;
+  Color[] colors = null;
 
-  /*
-   * The conservation slider percentage setting 
-   */
-  int inc = 30;
+  /* Set when threshold colouring to either pid_gaps or pid_nogaps */
+  protected boolean ignoreGaps = false;
 
   /**
    * Creates a new ResidueColourScheme object.
@@ -74,15 +59,11 @@ public class ResidueColourScheme implements ColourSchemeI
    *        ResidueProperties.aaIndex)
    * @param colors
    *          colours for symbols in sequences
-   * @param threshold
-   *          threshold for conservation shading
    */
-  public ResidueColourScheme(int[] aaOrnaIndex, Color[] colours,
-          int threshold)
+  public ResidueColourScheme(int[] aaOrnaIndex, Color[] colours)
   {
     symbolIndex = aaOrnaIndex;
     this.colors = colours;
-    this.threshold = threshold;
   }
 
   /**
@@ -106,241 +87,118 @@ public class ResidueColourScheme implements ColourSchemeI
   /**
    * Find a colour without an index in a sequence
    */
-  @Override
   public Color findColour(char c)
   {
-    return colors == null ? Color.white : colors[symbolIndex[c]];
-  }
+    Color colour = Color.white;
 
-  @Override
-  public Color findColour(char c, int j, SequenceI seq)
-  {
-    Color currentColour;
-
-    if (colors != null && symbolIndex != null && (threshold == 0)
-            || aboveThreshold(c, j))
+    if (!Comparison.isGap(c) && colors != null && symbolIndex != null
+            && c < symbolIndex.length
+            && symbolIndex[c] < colors.length)
     {
-      currentColour = colors[symbolIndex[c]];
-    }
-    else
-    {
-      currentColour = Color.white;
-    }
-
-    if (conservationColouring)
-    {
-      currentColour = applyConservation(currentColour, j);
+      colour = colors[symbolIndex[c]];
     }
 
-    return currentColour;
+    return colour;
   }
 
   /**
-   * Get the percentage threshold for this colour scheme
-   * 
-   * @return Returns the percentage threshold
+   * Default is to call the overloaded method that ignores consensus. A colour
+   * scheme that depends on consensus (for example, Blosum62), should override
+   * this method instead.
    */
   @Override
-  public int getThreshold()
+  public Color findColour(char c, int j, SequenceI seq,
+          String consensusResidue, float pid)
   {
-    return threshold;
+    return findColour(c, j, seq);
   }
 
   /**
-   * Sets the percentage consensus threshold value, and whether gaps are ignored
-   * in percentage identity calculation
-   * 
-   * @param consensusThreshold
-   * @param ignoreGaps
-   */
-  @Override
-  public void setThreshold(int consensusThreshold, boolean ignoreGaps)
-  {
-    threshold = consensusThreshold;
-    this.ignoreGaps = ignoreGaps;
-  }
-
-  /**
-   * Answers true if there is a consensus profile for the specified column, and
-   * the given residue matches the consensus (or joint consensus) residue for
-   * the column, and the percentage identity for the profile is equal to or
-   * greater than the current threshold; else answers false. The percentage
-   * calculation depends on whether or not we are ignoring gapped sequences.
-   * 
-   * @param residue
-   * @param column
-   *          (index into consensus profiles)
+   * Default implementation looks up the residue colour in a fixed scheme, or
+   * returns White if not found. Override this method for a colour scheme that
+   * depends on the column position or sequence.
    * 
+   * @param c
+   * @param j
+   * @param seq
    * @return
-   * @see #setThreshold(int, boolean)
    */
-  public boolean aboveThreshold(char residue, int column)
-  {
-    if ('a' <= residue && residue <= 'z')
-    {
-      // TO UPPERCASE !!!
-      // Faster than toUpperCase
-      residue -= ('a' - 'A');
-    }
-
-    if (consensus == null)
-    {
-      return false;
-    }
-
-    ProfileI profile = consensus.get(column);
-
-    /*
-     * test whether this is the consensus (or joint consensus) residue
-     */
-    if (profile != null
-            && profile.getModalResidue().contains(String.valueOf(residue)))
-    {
-      if (profile.getPercentageIdentity(ignoreGaps) >= threshold)
-      {
-        return true;
-      }
-    }
-
-    return false;
-  }
-
-  @Override
-  public boolean conservationApplied()
-  {
-    return conservationColouring;
-  }
-
-  @Override
-  public void setConservationApplied(boolean conservationApplied)
-  {
-    conservationColouring = conservationApplied;
-  }
-
-  @Override
-  public void setConservationInc(int i)
+  protected Color findColour(char c, int j, SequenceI seq)
   {
-    inc = i;
+    return findColour(c);
   }
 
   @Override
-  public int getConservationInc()
+  public void alignmentChanged(AnnotatedCollectionI alignment,
+          Map<SequenceI, SequenceCollectionI> hiddenReps)
   {
-    return inc;
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param consensus
-   *          DOCUMENT ME!
+   * Answers false if the colour scheme is nucleotide or peptide specific, and
+   * the data does not match, else true. Override to modify or extend this test
+   * as required.
    */
   @Override
-  public void setConsensus(ProfilesI consensus)
-  {
-    if (consensus == null)
-    {
-      return;
-    }
-
-    this.consensus = consensus;
-  }
-
-  @Override
-  public void setConservation(Conservation cons)
+  public boolean isApplicableTo(AnnotatedCollectionI ac)
   {
-    if (cons == null)
+    if (!isPeptideSpecific() && !isNucleotideSpecific())
     {
-      conservationColouring = false;
-      conservation = null;
+      return true;
     }
-    else
+    if (ac == null)
     {
-      conservationColouring = true;
-      int iSize = cons.getConsSequence().getLength();
-      conservation = new char[iSize];
-      for (int i = 0; i < iSize; i++)
-      {
-        conservation[i] = cons.getConsSequence().getCharAt(i);
-      }
+      return true;
     }
-
-  }
-
-  /**
-   * Applies a combination of column conservation score, and conservation
-   * percentage slider, to 'bleach' out the residue colours towards white.
-   * <p>
-   * If a column is fully conserved (identical residues, conservation score 11,
-   * shown as *), or all 10 physico-chemical properties are conserved
-   * (conservation score 10, shown as +), then the colour is left unchanged.
-   * <p>
-   * Otherwise a 'bleaching' factor is computed and applied to the colour. This
-   * is designed to fade colours for scores of 0-9 completely to white at slider
-   * positions ranging from 18% - 100% respectively.
-   * 
-   * @param currentColour
-   * @param column
-   * 
-   * @return bleached (or unmodified) colour
-   */
-  Color applyConservation(Color currentColour, int column)
-  {
-    if (conservation == null || conservation.length <= column)
-    {
-      return currentColour;
-    }
-    char conservationScore = conservation[column];
-
     /*
-     * if residues are fully conserved (* or 11), or all properties
-     * are conserved (+ or 10), leave colour unchanged
+     * pop-up menu on selection group before group created
+     * (no alignment context)
      */
-    if (conservationScore == '*' || conservationScore == '+'
-            || conservationScore == (char) 10
-            || conservationScore == (char) 11)
+    // TODO: add nucleotide flag to SequenceGroup?
+    if (ac instanceof SequenceGroup && ac.getContext() == null)
     {
-      return currentColour;
-    }
-
-    if (Comparison.isGap(conservationScore))
-    {
-      return Color.white;
+      return true;
     }
 
     /*
-     * convert score 0-9 to a bleaching factor 1.1 - 0.2
+     * inspect the data context (alignment) for residue type
      */
-    float bleachFactor = (11 - (conservationScore - '0')) / 10f;
+    boolean nucleotide = ac.isNucleotide();
 
     /*
-     * scale this up by 0-5 (percentage slider / 20)
-     * as a result, scores of:         0  1  2  3  4  5  6  7  8  9
-     * fade to white at slider value: 18 20 22 25 29 33 40 50 67 100%
+     * does data type match colour scheme type?
      */
-    bleachFactor *= (inc / 20f);
+    return (nucleotide && isNucleotideSpecific())
+            || (!nucleotide && isPeptideSpecific());
+  }
 
-    return ColorUtils.bleachColour(currentColour, bleachFactor);
+  /**
+   * Answers true if the colour scheme is normally only for peptide data
+   * 
+   * @return
+   */
+  public boolean isPeptideSpecific()
+  {
+    return false;
   }
 
-  @Override
-  public void alignmentChanged(AnnotatedCollectionI alignment,
-          Map<SequenceI, SequenceCollectionI> hiddenReps)
+  /**
+   * Answers true if the colour scheme is normally only for nucleotide data
+   * 
+   * @return
+   */
+  public boolean isNucleotideSpecific()
   {
+    return false;
   }
 
+  /**
+   * Default method returns true. Override this to return false in colour
+   * schemes that are not determined solely by the sequence symbol.
+   */
   @Override
-  public ColourSchemeI applyTo(AnnotatedCollectionI sg,
-          Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
+  public boolean isSimple()
   {
-    try
-    {
-      return getClass().newInstance();
-    } catch (Exception q)
-    {
-      throw new Error(MessageManager.formatMessage(
-              "error.implementation_error_cannot_duplicate_colour_scheme",
-              new String[] { getClass().getName() }), q);
-    }
+    return true;
   }
 }
index 94fdf71..1e6142d 100755 (executable)
@@ -625,13 +625,6 @@ public class ResidueProperties
     scoreMatrices.put("DNA", new ScoreMatrix("DNA", DNA, 1));
   }
 
-  public static final Color[] pidColours = { midBlue,
-      new Color(153, 153, 255),
-      // Color.lightGray,
-      new Color(204, 204, 255), };
-
-  public static final float[] pidThresholds = { 80, 60, 40, };
-
   public static List<String> STOP = Arrays.asList("TGA", "TAA", "TAG");
 
   public static String START = "ATG";
index 7eb920d..aa20121 100755 (executable)
  */
 package jalview.schemes;
 
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceI;
 
 import java.awt.Color;
+import java.util.Map;
 
 /**
  * DOCUMENT ME!
@@ -84,49 +87,30 @@ public class ScoreColourScheme extends ResidueColourScheme
   /**
    * DOCUMENT ME!
    * 
-   * @param s
-   *          DOCUMENT ME!
-   * @param j
+   * @param c
    *          DOCUMENT ME!
    * 
    * @return DOCUMENT ME!
    */
-  @Override
-  public Color findColour(char c, int j, SequenceI seq)
+  public Color makeColour(float c)
   {
-    if (threshold > 0)
-    {
-      if (!aboveThreshold(c, j))
-      {
-        return Color.white;
-      }
-    }
-
-    if (jalview.util.Comparison.isGap(c))
-    {
-      return Color.white;
-    }
-
-    Color currentColour = colors[ResidueProperties.aaIndex[c]];
-
-    if (conservationColouring)
-    {
-      currentColour = applyConservation(currentColour, j);
-    }
+    return new Color(c, (float) 0.0, (float) 1.0 - c);
+  }
 
-    return currentColour;
+  @Override
+  public String getSchemeName()
+  {
+    return "Score";
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param c
-   *          DOCUMENT ME!
-   * 
-   * @return DOCUMENT ME!
+   * Returns a new instance of this colour scheme with which the given data may
+   * be coloured
    */
-  public Color makeColour(float c)
+  @Override
+  public ColourSchemeI getInstance(AnnotatedCollectionI coll,
+          Map<SequenceI, SequenceCollectionI> hrs)
   {
-    return new Color(c, (float) 0.0, (float) 1.0 - c);
+    return new ScoreColourScheme(symbolIndex, scores, min, max);
   }
 }
index 1340de3..5f11c29 100755 (executable)
  */
 package jalview.schemes;
 
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+
 import java.awt.Color;
+import java.util.Map;
 
 /**
  * DOCUMENT ME!
@@ -47,8 +52,32 @@ public class StrandColourScheme extends ScoreColourScheme
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public Color makeColour(float c)
   {
     return new Color(c, c, (float) 1.0 - c);
   }
+
+  @Override
+  public boolean isPeptideSpecific()
+  {
+    return true;
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return JalviewColourScheme.Strand.toString();
+  }
+
+  /**
+   * Returns a new instance of this colour scheme with which the given data may
+   * be coloured
+   */
+  @Override
+  public ColourSchemeI getInstance(AnnotatedCollectionI coll,
+          Map<SequenceI, SequenceCollectionI> hrs)
+  {
+    return new StrandColourScheme();
+  }
 }
index 2be51c2..13d1d55 100644 (file)
@@ -31,6 +31,7 @@ import jalview.io.TCoffeeScoreFile;
 import java.awt.Color;
 import java.util.ArrayList;
 import java.util.IdentityHashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -44,20 +45,15 @@ import java.util.Map;
  */
 public class TCoffeeColourScheme extends ResidueColourScheme
 {
+  IdentityHashMap<SequenceI, Color[]> seqMap;
 
-  static final Color[] colors = { new Color(102, 102, 255), // #6666FF
-      new Color(0, 255, 0), // #00FF00
-      new Color(102, 255, 0), // #66FF00
-      new Color(204, 255, 0), // #CCFF00
-      new Color(255, 255, 0), // #FFFF00
-      new Color(255, 204, 0), // #FFCC00
-      new Color(255, 153, 0), // #FF9900
-      new Color(255, 102, 0), // #FF6600
-      new Color(255, 51, 0), // #FF3300
-      new Color(255, 34, 0) // #FF2000
-  };
+  /**
+   * Default constructor (required for Class.newInstance())
+   */
+  public TCoffeeColourScheme()
+  {
 
-  IdentityHashMap<SequenceI, Color[]> seqMap;
+  }
 
   /**
    * the color scheme needs to look at the alignment to get and cache T-COFFEE
@@ -71,6 +67,13 @@ public class TCoffeeColourScheme extends ResidueColourScheme
     alignmentChanged(alignment, null);
   }
 
+  /**
+   * Finds the TCoffeeScore annotation (if any) for each sequence and notes the
+   * annotation colour for each column position. The colours are fixed for
+   * scores 0-9 and are set when annotation is parsed.
+   * 
+   * @see TCoffeeScoreFile#annotateAlignment(AlignmentI, boolean)
+   */
   @Override
   public void alignmentChanged(AnnotatedCollectionI alignment,
           Map<SequenceI, SequenceCollectionI> hiddenReps)
@@ -80,7 +83,7 @@ public class TCoffeeColourScheme extends ResidueColourScheme
 
     // assume only one set of TCOFFEE scores - but could have more than one
     // potentially.
-    ArrayList<AlignmentAnnotation> annots = new ArrayList<AlignmentAnnotation>();
+    List<AlignmentAnnotation> annots = new ArrayList<AlignmentAnnotation>();
     // Search alignment to get all tcoffee annotation and pick one set of
     // annotation to use to colour seqs.
     seqMap = new IdentityHashMap<SequenceI, Color[]>();
@@ -119,9 +122,12 @@ public class TCoffeeColourScheme extends ResidueColourScheme
   @Override
   public Color findColour(char c, int j, SequenceI seq)
   {
-    Color[] cols;
-
-    if (seqMap == null || (cols = seqMap.get(seq)) == null)
+    if (seqMap == null)
+    {
+      return Color.WHITE;
+    }
+    Color[] cols = seqMap.get(seq);
+    if (cols == null)
     {
       // see above TODO about computing a colour for each residue in each
       // column: cc = _rcols[i][indexFor[c]];
@@ -136,9 +142,38 @@ public class TCoffeeColourScheme extends ResidueColourScheme
   }
 
   @Override
-  public ColourSchemeI applyTo(AnnotatedCollectionI sg,
+  public ColourSchemeI getInstance(AnnotatedCollectionI sg,
           Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
   {
     return new TCoffeeColourScheme(sg);
   }
+
+  /**
+   * Answers true if the data has TCoffee score annotation
+   */
+  @Override
+  public boolean isApplicableTo(AnnotatedCollectionI ac)
+  {
+    AnnotatedCollectionI alcontext = ac instanceof AlignmentI ? ac : ac
+            .getContext();
+    if (alcontext == null)
+    {
+      return false;
+    }
+    Iterable<AlignmentAnnotation> anns = alcontext
+            .findAnnotation(TCoffeeScoreFile.TCOFFEE_SCORE);
+    return anns.iterator().hasNext();
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return JalviewColourScheme.TCoffee.toString();
+  }
+
+  @Override
+  public boolean isSimple()
+  {
+    return false;
+  }
 }
index 8c46bba..ac8abbc 100755 (executable)
  */
 package jalview.schemes;
 
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+
+import java.util.Map;
+
 public class TaylorColourScheme extends ResidueColourScheme
 {
   public TaylorColourScheme()
   {
-    super(ResidueProperties.aaIndex, ResidueProperties.taylor, 0);
+    super(ResidueProperties.aaIndex, ResidueProperties.taylor);
+  }
+
+  @Override
+  public boolean isPeptideSpecific()
+  {
+    return true;
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return JalviewColourScheme.Taylor.toString();
+  }
+
+  /**
+   * Returns a new instance of this colour scheme with which the given data may
+   * be coloured
+   */
+  @Override
+  public ColourSchemeI getInstance(AnnotatedCollectionI coll,
+          Map<SequenceI, SequenceCollectionI> hrs)
+  {
+    return new TaylorColourScheme();
   }
 }
index 22422ff..67116b8 100755 (executable)
  */
 package jalview.schemes;
 
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+
 import java.awt.Color;
+import java.util.Map;
 
 /**
  * DOCUMENT ME!
@@ -47,8 +52,32 @@ public class TurnColourScheme extends ScoreColourScheme
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public Color makeColour(float c)
   {
     return new Color(c, 1 - c, 1 - c);
   }
+
+  @Override
+  public boolean isPeptideSpecific()
+  {
+    return true;
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return JalviewColourScheme.Turn.toString();
+  }
+
+  /**
+   * Returns a new instance of this colour scheme with which the given data may
+   * be coloured
+   */
+  @Override
+  public ColourSchemeI getInstance(AnnotatedCollectionI coll,
+          Map<SequenceI, SequenceCollectionI> hrs)
+  {
+    return new TurnColourScheme();
+  }
 }
index 9ae14ca..85bf54e 100755 (executable)
@@ -23,13 +23,23 @@ package jalview.schemes;
 import jalview.datamodel.AnnotatedCollectionI;
 import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceI;
+import jalview.util.ColorUtils;
+import jalview.util.StringUtils;
 
 import java.awt.Color;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.StringTokenizer;
 
 public class UserColourScheme extends ResidueColourScheme
 {
+  /*
+   * lookup (by symbol index) of lower case colours (if configured)
+   */
   Color[] lowerCaseColours;
 
   protected String schemeName;
@@ -46,37 +56,86 @@ public class UserColourScheme extends ResidueColourScheme
   }
 
   @Override
-  public ColourSchemeI applyTo(AnnotatedCollectionI sg,
+  public ColourSchemeI getInstance(AnnotatedCollectionI sg,
           Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
   {
-    UserColourScheme usc = new UserColourScheme(colors);
-    if (lowerCaseColours != null)
+    return new UserColourScheme(this);
+  }
+
+  /**
+   * Copy constructor
+   * 
+   * @return
+   */
+  protected UserColourScheme(UserColourScheme from)
+  {
+    this(from.colors);
+    schemeName = from.schemeName;
+    if (from.lowerCaseColours != null)
     {
-      usc.schemeName = new String(schemeName);
-      usc.lowerCaseColours = new Color[lowerCaseColours.length];
-      System.arraycopy(lowerCaseColours, 0, usc.lowerCaseColours, 0,
-              lowerCaseColours.length);
+      lowerCaseColours = new Color[lowerCaseColours.length];
+      System.arraycopy(from.lowerCaseColours, 0, lowerCaseColours, 0,
+              from.lowerCaseColours.length);
     }
-    return usc;
   }
 
+  /**
+   * Constructor for an animino acid colour scheme. The colour specification may
+   * be one of
+   * <ul>
+   * <li>an AWT colour name e.g. red</li>
+   * <li>an AWT hex rgb colour e.g. ff2288</li>
+   * <li>residue colours list e.g. D,E=red;K,R,H=0022FF;c=yellow</li>
+   * </ul>
+   * 
+   * @param colour
+   */
   public UserColourScheme(String colour)
   {
     super(ResidueProperties.aaIndex);
-    Color col = getColourFromString(colour);
+
+    if (colour.contains("="))
+    {
+      /*
+       * a list of colours per residue(s)
+       */
+      parseAppletParameter(colour);
+      return;
+    }
+
+    Color col = ColorUtils.parseColourString(colour);
 
     if (col == null)
     {
       System.out.println("Making colour from name: " + colour);
-      col = createColourFromName(colour);
+      col = ColorUtils.createColourFromName(colour);
     }
 
-    colors = new Color[24];
-    for (int i = 0; i < 24; i++)
+    setAll(col);
+    schemeName = colour;
+  }
+
+  /**
+   * Sets all symbols to the specified colour
+   * 
+   * @param col
+   */
+  protected void setAll(Color col)
+  {
+    if (symbolIndex == null)
+    {
+      return;
+    }
+    int max = 0;
+    for (int index : symbolIndex)
+    {
+      max = Math.max(max, index);
+    }
+    colors = new Color[max + 1];
+    for (int i = 0; i <= max; i++)
     {
       colors[i] = col;
     }
-    schemeName = colour;
   }
 
   public Color[] getColours()
@@ -99,77 +158,25 @@ public class UserColourScheme extends ResidueColourScheme
     return schemeName;
   }
 
-  public static Color getColourFromString(String colour)
-  {
-    if (colour == null)
-    {
-      return null;
-    }
-    colour = colour.trim();
-
-    Color col = null;
-    try
-    {
-      int value = Integer.parseInt(colour, 16);
-      col = new Color(value);
-    } catch (NumberFormatException ex)
-    {
-    }
-
-    if (col == null)
-    {
-      col = ColourSchemeProperty.getAWTColorFromName(colour);
-    }
-
-    if (col == null)
-    {
-      try
-      {
-        java.util.StringTokenizer st = new java.util.StringTokenizer(
-                colour, ",");
-        int r = Integer.parseInt(st.nextToken());
-        int g = Integer.parseInt(st.nextToken());
-        int b = Integer.parseInt(st.nextToken());
-        col = new Color(r, g, b);
-      } catch (Exception ex)
-      {
-      }
-    }
-
-    return col;
-
-  }
-
-  public static Color createColourFromName(String name)
+  /**
+   * Parse and save residue colours specified as (for example)
+   * 
+   * <pre>
+   *     D,E=red; K,R,H=0022FF; c=100,50,75
+   * </pre>
+   * 
+   * This should be a semi-colon separated list of colours, which may be defined
+   * by colour name, hex value or comma-separated RGB triple. Each colour is
+   * defined for a comma-separated list of amino acid single letter codes. (Note
+   * that this also allows a colour scheme to be defined for ACGT, but not for
+   * U.)
+   * 
+   * @param paramValue
+   */
+  void parseAppletParameter(String paramValue)
   {
-    int r, g, b;
-
-    int lsize = name.length();
-    int start = 0, end = lsize / 3;
-
-    int rgbOffset = Math.abs(name.hashCode() % 10) * 15;
-
-    r = Math.abs(name.substring(start, end).hashCode() + rgbOffset) % 210 + 20;
-    start = end;
-    end += lsize / 3;
-    if (end > lsize)
-    {
-      end = lsize;
-    }
+    setAll(Color.white);
 
-    g = Math.abs(name.substring(start, end).hashCode() + rgbOffset) % 210 + 20;
-
-    b = Math.abs(name.substring(end).hashCode() + rgbOffset) % 210 + 20;
-
-    Color color = new Color(r, g, b);
-
-    return color;
-  }
-
-  public void parseAppletParameter(String paramValue)
-  {
-    // TODO: need a function to generate appletParameter colour string from a
-    // UCS
     StringTokenizer st = new StringTokenizer(paramValue, ";");
     StringTokenizer st2;
     String token = null, colour, residues;
@@ -184,43 +191,42 @@ public class UserColourScheme extends ResidueColourScheme
         st2 = new StringTokenizer(residues, " ,");
         while (st2.hasMoreTokens())
         {
-          token = st2.nextToken();
+          String residue = st2.nextToken();
 
-          if (ResidueProperties.aaIndex[token.charAt(0)] == -1)
+          int colIndex = ResidueProperties.aaIndex[residue.charAt(0)];
+          if (colIndex == -1)
           {
             continue;
           }
 
-          int colIndex = ResidueProperties.aaIndex[token.charAt(0)];
-
-          if (token.equalsIgnoreCase("lowerCase"))
+          if (residue.equalsIgnoreCase("lowerCase"))
           {
             if (lowerCaseColours == null)
             {
-              lowerCaseColours = new Color[23];
+              lowerCaseColours = new Color[colors.length];
             }
-            for (int i = 0; i < 23; i++)
+            for (int i = 0; i < lowerCaseColours.length; i++)
             {
               if (lowerCaseColours[i] == null)
               {
-                lowerCaseColours[i] = getColourFromString(colour);
+                lowerCaseColours[i] = ColorUtils.parseColourString(colour);
               }
             }
 
             continue;
           }
 
-          if (token.equals(token.toLowerCase()))
+          if (residue.equals(residue.toLowerCase()))
           {
             if (lowerCaseColours == null)
             {
-              lowerCaseColours = new Color[23];
+              lowerCaseColours = new Color[colors.length];
             }
-            lowerCaseColours[colIndex] = getColourFromString(colour);
+            lowerCaseColours[colIndex] = ColorUtils.parseColourString(colour);
           }
           else
           {
-            colors[colIndex] = getColourFromString(colour);
+            colors[colIndex] = ColorUtils.parseColourString(colour);
           }
         }
       }
@@ -232,39 +238,115 @@ public class UserColourScheme extends ResidueColourScheme
 
   }
 
-  @Override
-  public Color findColour(char c, int j, SequenceI seq)
+  public void setLowerCaseColours(Color[] lcolours)
   {
-    Color currentColour;
-    int index = ResidueProperties.aaIndex[c];
+    lowerCaseColours = lcolours;
+  }
 
-    if ((threshold == 0) || aboveThreshold(c, j))
+  /**
+   * Returns the colour for the given residue character. If the residue is
+   * lower-case, and there is a specific colour defined for lower case, that
+   * colour is returned, else the colour for the upper case residue.
+   */
+  @Override
+  public Color findColour(char c)
+  {
+    if ('a' <= c && c <= 'z' && lowerCaseColours != null)
     {
-      if (lowerCaseColours != null && 'a' <= c && c <= 'z')
-      {
-        currentColour = lowerCaseColours[index];
-      }
-      else
+      Color colour = lowerCaseColours[symbolIndex[c]];
+      if (colour != null)
       {
-        currentColour = colors[index];
+        return colour;
       }
     }
-    else
+    return super.findColour(c);
+  }
+
+  /**
+   * Answers the customised name of the colour scheme, if it has one, else
+   * "User Defined"
+   */
+  @Override
+  public String getSchemeName()
+  {
+    if (schemeName != null && schemeName.length() > 0)
     {
-      currentColour = Color.white;
+      return schemeName;
     }
+    return "User Defined";
+  }
+
+  /**
+   * Generate an applet colour parameter like A,C,D=12ffe9;Q,W=2393fd;w=9178dd
+   * 
+   * @return
+   */
+  public String toAppletParameter()
+  {
+    /*
+     * step 1: build a map from colours to the symbol(s) that have the colour
+     */
+    Map<Color, List<String>> colours = new HashMap<Color, List<String>>();
 
-    if (conservationColouring)
+    for (char symbol = 'A'; symbol <= 'Z'; symbol++)
     {
-      currentColour = applyConservation(currentColour, j);
+      String residue = String.valueOf(symbol);
+      int index = symbolIndex[symbol];
+      Color c = colors[index];
+      if (c != null && !c.equals(Color.white))
+      {
+        if (colours.get(c) == null)
+        {
+          colours.put(c, new ArrayList<String>());
+        }
+        colours.get(c).add(residue);
+      }
+      if (lowerCaseColours != null)
+      {
+        c = lowerCaseColours[index];
+        if (c != null && !c.equals(Color.white))
+        {
+          residue = residue.toLowerCase();
+          if (colours.get(c) == null)
+          {
+            colours.put(c, new ArrayList<String>());
+          }
+          colours.get(c).add(residue);
+        }
+      }
     }
 
-    return currentColour;
-  }
+    /*
+     * step 2: make a list of { A,G,R=12f9d6 } residues/colour specs
+     */
+    List<String> residueColours = new ArrayList<String>();
+    for (Entry<Color, List<String>> cols : colours.entrySet())
+    {
+      boolean first = true;
+      StringBuilder sb = new StringBuilder();
+      for (String residue : cols.getValue())
+      {
+        if (!first)
+        {
+          sb.append(",");
+        }
+        sb.append(residue);
+        first = false;
+      }
+      sb.append("=");
+      /*
+       * get color as hex value, dropping the alpha (ff) part
+       */
+      String hexString = Integer.toHexString(cols.getKey().getRGB())
+              .substring(2);
+      sb.append(hexString);
+      residueColours.add(sb.toString());
+    }
 
-  public void setLowerCaseColours(Color[] lcolours)
-  {
-    lowerCaseColours = lcolours;
+    /*
+     * sort and output
+     */
+    Collections.sort(residueColours);
+    return StringUtils.listToDelimitedString(residueColours, ";");
   }
-
 }
index 8fa1656..c32a39c 100755 (executable)
  */
 package jalview.schemes;
 
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+
+import java.util.Map;
+
 /**
  * DOCUMENT ME!
  * 
@@ -33,6 +39,29 @@ public class ZappoColourScheme extends ResidueColourScheme
    */
   public ZappoColourScheme()
   {
-    super(ResidueProperties.aaIndex, ResidueProperties.zappo, 0);
+    super(ResidueProperties.aaIndex, ResidueProperties.zappo);
+  }
+
+  @Override
+  public boolean isPeptideSpecific()
+  {
+    return true;
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return JalviewColourScheme.Zappo.toString();
+  }
+
+  /**
+   * Returns a new instance of this colour scheme with which the given data may
+   * be coloured
+   */
+  @Override
+  public ColourSchemeI getInstance(AnnotatedCollectionI coll,
+          Map<SequenceI, SequenceCollectionI> hrs)
+  {
+    return new ZappoColourScheme();
   }
 }
index 063eacf..fda08fd 100644 (file)
  */
 package jalview.structures.models;
 
+import jalview.api.AlignmentViewPanel;
+import jalview.api.FeatureRenderer;
+import jalview.api.SequenceRenderer;
 import jalview.api.StructureSelectionManagerProvider;
 import jalview.api.structures.JalviewStructureDisplayI;
 import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
 import jalview.io.DataSourceType;
+import jalview.schemes.ColourSchemeI;
 import jalview.structure.AtomSpec;
 import jalview.structure.StructureListener;
 import jalview.structure.StructureMapping;
+import jalview.structure.StructureMappingcommandSet;
 import jalview.structure.StructureSelectionManager;
 import jalview.util.Comparison;
 import jalview.util.MessageManager;
 
+import java.awt.Color;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -85,6 +92,8 @@ public abstract class AAStructureBindingModel extends
    */
   protected String[] modelFileNames = null;
 
+  public String fileLoadingError;
+
   /**
    * Data bean class to simplify parameterisation in superposeStructures
    */
@@ -688,4 +697,80 @@ public abstract class AAStructureBindingModel extends
   {
     return null;
   }
+
+  public abstract void setJalviewColourScheme(ColourSchemeI cs);
+
+  public abstract void superposeStructures(AlignmentI[] als, int[] alm,
+          ColumnSelection[] alc);
+
+  public abstract void setBackgroundColour(Color col);
+
+  protected abstract StructureMappingcommandSet[] getColourBySequenceCommands(
+          String[] files, SequenceRenderer sr, FeatureRenderer fr,
+          AlignmentI alignment);
+
+  /**
+   * returns the current featureRenderer that should be used to colour the
+   * structures
+   * 
+   * @param alignment
+   * 
+   * @return
+   */
+  public abstract FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment);
+
+  /**
+   * returns the current sequenceRenderer that should be used to colour the
+   * structures
+   * 
+   * @param alignment
+   * 
+   * @return
+   */
+  public abstract SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment);
+
+  protected abstract void colourBySequence(
+          StructureMappingcommandSet[] colourBySequenceCommands);
+
+  public abstract void colourByChain();
+
+  public abstract void colourByCharge();
+
+  /**
+   * colour any structures associated with sequences in the given alignment
+   * using the getFeatureRenderer() and getSequenceRenderer() renderers but only
+   * if colourBySequence is enabled.
+   */
+  public void colourBySequence(AlignmentViewPanel alignmentv)
+  {
+    boolean showFeatures = alignmentv.getAlignViewport()
+            .isShowSequenceFeatures();
+    if (!colourBySequence || !isLoadingFinished())
+    {
+      return;
+    }
+    if (getSsm() == null)
+    {
+      return;
+    }
+    String[] files = getPdbFile();
+  
+    SequenceRenderer sr = getSequenceRenderer(alignmentv);
+  
+    FeatureRenderer fr = null;
+    if (showFeatures)
+    {
+      fr = getFeatureRenderer(alignmentv);
+    }
+    AlignmentI alignment = alignmentv.getAlignment();
+  
+    StructureMappingcommandSet[] colourBySequenceCommands = getColourBySequenceCommands(
+            files, sr, fr, alignment);
+    colourBySequence(colourBySequenceCommands);
+  }
+
+  public boolean hasFileLoadingError()
+  {
+    return fileLoadingError != null && fileLoadingError.length() > 0;
+  }
 }
index 525bfdb..d7829df 100644 (file)
@@ -191,4 +191,167 @@ public class ColorUtils
       return new Color(red, green, blue);
     }
   }
+
+  /**
+   * Parses a string into a Color, where the accepted formats are
+   * <ul>
+   * <li>an AWT colour name e.g. white</li>
+   * <li>a hex colour value (without prefix) e.g. ff0000</li>
+   * <li>an rgb triple e.g. 100,50,150</li>
+   * </ul>
+   * 
+   * @param colour
+   * @return the parsed colour, or null if parsing fails
+   */
+  public static Color parseColourString(String colour)
+  {
+    if (colour == null)
+    {
+      return null;
+    }
+    colour = colour.trim();
+  
+    Color col = null;
+    try
+    {
+      int value = Integer.parseInt(colour, 16);
+      col = new Color(value);
+    } catch (NumberFormatException ex)
+    {
+    }
+  
+    if (col == null)
+    {
+      col = ColorUtils.getAWTColorFromName(colour);
+    }
+  
+    if (col == null)
+    {
+      try
+      {
+        String[] tokens = colour.split(",");
+        if (tokens.length == 3)
+        {
+          int r = Integer.parseInt(tokens[0].trim());
+          int g = Integer.parseInt(tokens[1].trim());
+          int b = Integer.parseInt(tokens[2].trim());
+          col = new Color(r, g, b);
+        }
+      } catch (Exception ex)
+      {
+        // non-numeric token or out of 0-255 range
+      }
+    }
+  
+    return col;
+  }
+
+  /**
+   * Constructs a colour from a text string. The hashcode of the whole string is
+   * scaled to the range 0-135. This is added to RGB values made from the
+   * hashcode of each third of the string, and scaled to the range 20-229.
+   * 
+   * @param name
+   * @return
+   */
+  public static Color createColourFromName(String name)
+  {
+    if (name == null)
+    {
+      return Color.white;
+    }
+    int lsize = name.length();
+    int start = 0;
+    int end = lsize / 3;
+  
+    int rgbOffset = Math.abs(name.hashCode() % 10) * 15; // 0-135
+  
+    /*
+     * red: first third
+     */
+    int r = Math.abs(name.substring(start, end).hashCode() + rgbOffset) % 210 + 20;
+    start = end;
+    end += lsize / 3;
+    if (end > lsize)
+    {
+      end = lsize;
+    }
+  
+    /*
+     * green: second third
+     */
+    int g = Math.abs(name.substring(start, end).hashCode() + rgbOffset) % 210 + 20;
+  
+    /*
+     * blue: third third
+     */
+    int b = Math.abs(name.substring(end).hashCode() + rgbOffset) % 210 + 20;
+  
+    Color color = new Color(r, g, b);
+  
+    return color;
+  }
+
+  /**
+   * Returns the Color constant for a given colour name e.g. "pink", or null if
+   * the name is not recognised
+   * 
+   * @param name
+   * @return
+   */
+  public static Color getAWTColorFromName(String name)
+  {
+    if (name == null)
+    {
+      return null;
+    }
+    Color col = null;
+    name = name.toLowerCase();
+  
+    // or make a static map; or use reflection on the field name
+    switch (name)
+    {
+    case "black":
+      col = Color.black;
+      break;
+    case "blue":
+      col = Color.blue;
+      break;
+    case "cyan":
+      col = Color.cyan;
+      break;
+    case "darkgray":
+      col = Color.darkGray;
+      break;
+    case "gray":
+      col = Color.gray;
+      break;
+    case "green":
+      col = Color.green;
+      break;
+    case "lightgray":
+      col = Color.lightGray;
+      break;
+    case "magenta":
+      col = Color.magenta;
+      break;
+    case "orange":
+      col = Color.orange;
+      break;
+    case "pink":
+      col = Color.pink;
+      break;
+    case "red":
+      col = Color.red;
+      break;
+    case "white":
+      col = Color.white;
+      break;
+    case "yellow":
+      col = Color.yellow;
+      break;
+    }
+  
+    return col;
+  }
 }
index f35339c..2e30132 100644 (file)
@@ -320,7 +320,7 @@ public final class MappingUtils
      * Copy group name, colours etc, but not sequences or sequence colour scheme
      */
     SequenceGroup mappedGroup = new SequenceGroup(sg);
-    mappedGroup.cs = mapTo.getGlobalColourScheme();
+    mappedGroup.setColourScheme(mapTo.getGlobalColourScheme());
     mappedGroup.clear();
 
     int minStartCol = -1;
index fecccb0..8fa14ae 100644 (file)
@@ -42,9 +42,9 @@ import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
-import jalview.schemes.Blosum62ColourScheme;
+import jalview.renderer.ResidueShader;
+import jalview.renderer.ResidueShaderI;
 import jalview.schemes.ColourSchemeI;
-import jalview.schemes.PIDColourScheme;
 import jalview.structure.CommandListener;
 import jalview.structure.StructureSelectionManager;
 import jalview.structure.VamsasSource;
@@ -597,7 +597,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
 
   protected boolean ignoreGapsInConsensusCalculation = false;
 
-  protected ColourSchemeI globalColourScheme = null;
+  protected ResidueShaderI residueShading;
 
   @Override
   public void setGlobalColourScheme(ColourSchemeI cs)
@@ -605,74 +605,51 @@ public abstract class AlignmentViewport implements AlignViewportI,
     // TODO: logic refactored from AlignFrame changeColour -
     // TODO: autorecalc stuff should be changed to rely on the worker system
     // check to see if we should implement a changeColour(cs) method rather than
-    // put th logic in here
+    // put the logic in here
     // - means that caller decides if they want to just modify state and defer
     // calculation till later or to do all calculations in thread.
     // via changecolour
-    globalColourScheme = cs;
-    boolean recalc = false;
+
+    /*
+     * only instantiate alignment colouring once, thereafter update it;
+     * this means that any conservation or PID threshold settings
+     * persist when the alignment colour scheme is changed
+     */
+    if (residueShading == null)
+    {
+      residueShading = new ResidueShader(viewStyle);
+    }
+    residueShading.setColourScheme(cs);
+
+    // TODO: do threshold and increment belong in ViewStyle or ResidueShader?
+    // ...problem: groups need these, but do not currently have a ViewStyle
+
     if (cs != null)
     {
-      recalc = getConservationSelected();
-      if (getAbovePIDThreshold() || cs instanceof PIDColourScheme
-              || cs instanceof Blosum62ColourScheme)
-      {
-        recalc = true;
-        cs.setThreshold(viewStyle.getThreshold(),
-                ignoreGapsInConsensusCalculation);
-      }
-      else
+      if (getConservationSelected())
       {
-        cs.setThreshold(0, ignoreGapsInConsensusCalculation);
+        residueShading.setConservation(hconservation);
       }
-      if (recalc)
-      {
-        cs.setConsensus(hconsensus);
-        cs.setConservation(hconservation);
-      }
-      cs.setConservationApplied(getConservationSelected());
-      cs.alignmentChanged(alignment, hiddenRepSequences);
+      residueShading.alignmentChanged(alignment, hiddenRepSequences);
     }
+
+    /*
+     * if 'apply colour to all groups' is selected... do so
+     * (but don't transfer any colour threshold settings to groups)
+     */
     if (getColourAppliesToAllGroups())
     {
       for (SequenceGroup sg : getAlignment().getGroups())
       {
-        if (cs == null)
+        /*
+         * retain any colour thresholds per group while
+         * changing choice of colour scheme (JAL-2386)
+         */
+        sg.setColourScheme(cs);
+        if (cs != null)
         {
-          sg.cs = null;
-          continue;
-        }
-        sg.cs = cs.applyTo(sg, getHiddenRepSequences());
-        sg.setConsPercGaps(ConsPercGaps);
-        if (getAbovePIDThreshold() || cs instanceof PIDColourScheme
-                || cs instanceof Blosum62ColourScheme)
-        {
-          sg.cs.setThreshold(viewStyle.getThreshold(),
-                  isIgnoreGapsConsensus());
-          recalc = true;
-        }
-        else
-        {
-          sg.cs.setThreshold(0, isIgnoreGapsConsensus());
-        }
-
-        if (getConservationSelected())
-        {
-          sg.cs.setConservationApplied(true);
-          recalc = true;
-        }
-        else
-        {
-          sg.cs.setConservation(null);
-          // sg.cs.setThreshold(0, getIgnoreGapsConsensus());
-        }
-        if (recalc)
-        {
-          sg.recalcConservation();
-        }
-        else
-        {
-          sg.cs.alignmentChanged(sg, hiddenRepSequences);
+          sg.getGroupColourScheme()
+                  .alignmentChanged(sg, hiddenRepSequences);
         }
       }
     }
@@ -681,7 +658,14 @@ public abstract class AlignmentViewport implements AlignViewportI,
   @Override
   public ColourSchemeI getGlobalColourScheme()
   {
-    return globalColourScheme;
+    return residueShading == null ? null : residueShading
+            .getColourScheme();
+  }
+
+  @Override
+  public ResidueShaderI getResidueShading()
+  {
+    return residueShading;
   }
 
   protected AlignmentAnnotation consensus;
@@ -941,7 +925,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
     hconsensus = null;
     hcomplementConsensus = null;
     // colour scheme may hold reference to consensus
-    globalColourScheme = null;
+    residueShading = null;
     // TODO remove listeners from changeSupport?
     changeSupport = null;
     setAlignment(null);
@@ -1089,7 +1073,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
   }
 
   /**
-   * Set the selection group for this window.
+   * Set the selection group for this window. Also sets the current alignment as
+   * the context for the group, if it does not already have one.
    * 
    * @param sg
    *          - group holding references to sequences in this alignment view
@@ -1099,6 +1084,10 @@ public abstract class AlignmentViewport implements AlignViewportI,
   public void setSelectionGroup(SequenceGroup sg)
   {
     selectionGroup = sg;
+    if (sg != null && sg.getContext() == null)
+    {
+      sg.setContext(alignment);
+    }
   }
 
   public void setHiddenColumns(ColumnSelection colsel)
@@ -1211,9 +1200,9 @@ public abstract class AlignmentViewport implements AlignViewportI,
     if (ap != null)
     {
       updateConsensus(ap);
-      if (globalColourScheme != null)
+      if (residueShading != null)
       {
-        globalColourScheme.setThreshold(globalColourScheme.getThreshold(),
+        residueShading.setThreshold(residueShading.getThreshold(),
                 ignoreGapsInConsensusCalculation);
       }
     }
@@ -1849,7 +1838,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
       selectionGroup.setEndRes(alWidth - 1);
     }
 
-    resetAllColourSchemes();
+    updateAllColourSchemes();
     calculator.restartWorkers();
     // alignment.adjustSequenceAnnotations();
   }
@@ -1857,17 +1846,17 @@ public abstract class AlignmentViewport implements AlignViewportI,
   /**
    * reset scope and do calculations for all applied colourschemes on alignment
    */
-  void resetAllColourSchemes()
+  void updateAllColourSchemes()
   {
-    ColourSchemeI cs = globalColourScheme;
-    if (cs != null)
+    ResidueShaderI rs = residueShading;
+    if (rs != null)
     {
-      cs.alignmentChanged(alignment, hiddenRepSequences);
+      rs.alignmentChanged(alignment, hiddenRepSequences);
 
-      cs.setConsensus(hconsensus);
-      if (cs.conservationApplied())
+      rs.setConsensus(hconsensus);
+      if (rs.conservationApplied())
       {
-        cs.setConservation(Conservation.calculateConservation("All",
+        rs.setConservation(Conservation.calculateConservation("All",
                 alignment.getSequences(), 0, alignment.getWidth(), false,
                 getConsPercGaps(), false));
       }
index c1ad465..8468329 100644 (file)
@@ -28,7 +28,7 @@ import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.renderer.seqfeatures.FeatureRenderer;
 import jalview.schemes.FeatureColour;
-import jalview.schemes.UserColourScheme;
+import jalview.util.ColorUtils;
 
 import java.awt.Color;
 import java.beans.PropertyChangeListener;
@@ -542,7 +542,7 @@ public abstract class FeatureRendererModel implements
     FeatureColourI fc = featureColours.get(featureType);
     if (fc == null)
     {
-      Color col = UserColourScheme.createColourFromName(featureType);
+      Color col = ColorUtils.createColourFromName(featureType);
       fc = new FeatureColour(col);
       featureColours.put(featureType, fc);
     }
index debe45d..0c7e69a 100644 (file)
@@ -28,7 +28,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.ProfilesI;
 import jalview.datamodel.SequenceI;
-import jalview.schemes.ColourSchemeI;
+import jalview.renderer.ResidueShaderI;
 
 public class ConsensusThread extends AlignCalcWorker
 {
@@ -147,11 +147,10 @@ public class ConsensusThread extends AlignCalcWorker
    */
   protected void setColourSchemeConsensus(ProfilesI hconsensus)
   {
-    ColourSchemeI globalColourScheme = alignViewport
-            .getGlobalColourScheme();
-    if (globalColourScheme != null)
+    ResidueShaderI cs = alignViewport.getResidueShading();
+    if (cs != null)
     {
-      globalColourScheme.setConsensus(hconsensus);
+      cs.setConsensus(hconsensus);
     }
   }
 
index 0cf76e0..001f6a8 100644 (file)
@@ -29,7 +29,7 @@ import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
 import jalview.schemes.FeatureColour;
-import jalview.schemes.UserColourScheme;
+import jalview.util.ColorUtils;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
 import jalview.ws.params.WsParamSetI;
 
@@ -308,7 +308,7 @@ public class AADisorderClient extends JabawsCalcWorker
                 annot.description += "<br/>" + threshNote;
               }
               annot.description += "</html>";
-              Color col = UserColourScheme.createColourFromName(typeName
+              Color col = ColorUtils.createColourFromName(typeName
                       + scr.getMethod());
               for (int p = 0, ps = annot.annotations.length; p < ps; p++)
               {
index 618bac5..7af77f5 100644 (file)
@@ -611,6 +611,12 @@ public class AlignmentTest
     AlignmentAnnotation ann = iter.next();
     assertEquals("D.melanogaster.2", ann.sequenceRef.getName());
     assertFalse(iter.hasNext());
+
+    // invalid id
+    anns = al.findAnnotation("CalcIdForD.melanogaster.?");
+    assertFalse(iter.hasNext());
+    anns = al.findAnnotation(null);
+    assertFalse(iter.hasNext());
   }
 
   @Test(groups = { "Functional" })
diff --git a/test/jalview/datamodel/SequenceGroupTest.java b/test/jalview/datamodel/SequenceGroupTest.java
new file mode 100644 (file)
index 0000000..243bd53
--- /dev/null
@@ -0,0 +1,115 @@
+package jalview.datamodel;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import jalview.schemes.NucleotideColourScheme;
+
+import org.testng.annotations.Test;
+
+public class SequenceGroupTest
+{
+  @Test
+  public void testAddSequence()
+  {
+    SequenceGroup sg = new SequenceGroup();
+    assertTrue(sg.getSequences().isEmpty());
+
+    SequenceI seq1 = new Sequence("seq1", "abc");
+    SequenceI seq2 = new Sequence("seq2", "abc");
+    SequenceI seq3 = new Sequence(seq1);
+
+    sg.addSequence(null, false);
+    assertTrue(sg.getSequences().isEmpty());
+    sg.addSequence(seq1, false);
+    assertEquals(sg.getSequences().size(), 1);
+    assertTrue(sg.getSequences().contains(seq1));
+    // adding the same sequence again does nothing
+    sg.addSequence(seq1, false);
+    assertEquals(sg.getSequences().size(), 1);
+    assertTrue(sg.getSequences().contains(seq1));
+    sg.addSequence(seq2, false);
+    sg.addSequence(seq2, false);
+    sg.addSequence(seq3, false);
+    assertEquals(sg.getSequences().size(), 3);
+    assertTrue(sg.getSequences().contains(seq1));
+    assertTrue(sg.getSequences().contains(seq2));
+    assertTrue(sg.getSequences().contains(seq3));
+  }
+
+  @Test
+  public void testAddOrRemove()
+  {
+    SequenceGroup sg = new SequenceGroup();
+    assertTrue(sg.getSequences().isEmpty());
+  
+    SequenceI seq1 = new Sequence("seq1", "abc");
+    SequenceI seq2 = new Sequence("seq2", "abc");
+    SequenceI seq3 = new Sequence(seq1);
+  
+    sg.addOrRemove(seq1, false);
+    assertEquals(sg.getSequences().size(), 1);
+    sg.addOrRemove(seq2, false);
+    assertEquals(sg.getSequences().size(), 2);
+    sg.addOrRemove(seq3, false);
+    assertEquals(sg.getSequences().size(), 3);
+    assertTrue(sg.getSequences().contains(seq1));
+    assertTrue(sg.getSequences().contains(seq2));
+    assertTrue(sg.getSequences().contains(seq3));
+    sg.addOrRemove(seq1, false);
+    assertEquals(sg.getSequences().size(), 2);
+    assertFalse(sg.getSequences().contains(seq1));
+  }
+
+  @Test
+  public void testGetColourScheme()
+  {
+    SequenceGroup sg = new SequenceGroup();
+    assertNotNull(sg.getGroupColourScheme());
+    assertNull(sg.getColourScheme());
+
+    sg.setGroupColourScheme(null);
+    assertNull(sg.getColourScheme());
+
+    NucleotideColourScheme scheme = new NucleotideColourScheme();
+    sg.setColourScheme(scheme);
+    assertSame(scheme, sg.getColourScheme());
+  }
+
+  @Test
+  public void testSetContext()
+  {
+    SequenceGroup sg1 = new SequenceGroup();
+    SequenceGroup sg2 = new SequenceGroup();
+    SequenceGroup sg3 = new SequenceGroup();
+    assertNull(sg1.getContext());
+    sg1.setContext(null);
+    assertNull(sg1.getContext());
+    try
+    {
+      sg1.setContext(sg1); // self-reference :-O
+      fail("Expected exception");
+    } catch (IllegalArgumentException e)
+    {
+      // expected
+      assertNull(sg1.getContext());
+    }
+    sg1.setContext(sg2);
+    assertSame(sg2, sg1.getContext());
+    sg2.setContext(sg3);
+    try
+    {
+      sg3.setContext(sg1); // circular reference :-O
+      fail("Expected exception");
+    } catch (IllegalArgumentException e)
+    {
+      // expected
+      assertNull(sg3.getContext());
+    }
+  }
+}
index d0ea751..ffb886c 100644 (file)
@@ -30,6 +30,7 @@ import java.util.Arrays;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.SortedMap;
 
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -47,7 +48,7 @@ public class ChimeraCommandsTest
   @Test(groups = { "Functional" })
   public void testAddColourRange()
   {
-    Map<Color, Map<Integer, Map<String, List<int[]>>>> map = new LinkedHashMap<Color, Map<Integer, Map<String, List<int[]>>>>();
+    Map<Color, SortedMap<Integer, Map<String, List<int[]>>>> map = new LinkedHashMap<Color, SortedMap<Integer, Map<String, List<int[]>>>>();
     ChimeraCommands.addColourRange(map, Color.pink, 1, 2, 4, "A");
     ChimeraCommands.addColourRange(map, Color.pink, 1, 8, 8, "A");
     ChimeraCommands.addColourRange(map, Color.pink, 1, 5, 7, "B");
@@ -96,7 +97,7 @@ public class ChimeraCommandsTest
   public void testBuildColourCommands()
   {
 
-    Map<Color, Map<Integer, Map<String, List<int[]>>>> map = new LinkedHashMap<Color, Map<Integer, Map<String, List<int[]>>>>();
+    Map<Color, SortedMap<Integer, Map<String, List<int[]>>>> map = new LinkedHashMap<Color, SortedMap<Integer, Map<String, List<int[]>>>>();
     ChimeraCommands.addColourRange(map, Color.blue, 0, 2, 5, "A");
     ChimeraCommands.addColourRange(map, Color.blue, 0, 7, 7, "B");
     ChimeraCommands.addColourRange(map, Color.blue, 0, 9, 23, "A");
index 60db9dd..2ea94a4 100644 (file)
  */
 package jalview.gui;
 
-import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertFalse;
-import static org.testng.AssertJUnit.assertTrue;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotSame;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
 
+import jalview.bin.Cache;
+import jalview.bin.Jalview;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+import jalview.io.Jalview2xmlTests;
+import jalview.renderer.ResidueShaderI;
+import jalview.schemes.BuriedColourScheme;
+import jalview.schemes.HelixColourScheme;
+import jalview.schemes.JalviewColourScheme;
+import jalview.schemes.StrandColourScheme;
+import jalview.schemes.TurnColourScheme;
+import jalview.util.MessageManager;
 
+import java.awt.Color;
 import java.util.List;
 
+import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 public class AlignFrameTest
 {
+  AlignFrame af;
 
   @BeforeClass(alwaysRun = true)
   public void setUpJvOptionPane()
@@ -59,26 +78,26 @@ public class AlignFrameTest
     seq2.addSequenceFeature(new SequenceFeature("Turn", "", 7, 9,
             Float.NaN, null));
     AlignmentI al = new Alignment(new SequenceI[] { seq1, seq2 });
-    AlignFrame af = new AlignFrame(al, al.getWidth(), al.getHeight());
+    AlignFrame alignFrame = new AlignFrame(al, al.getWidth(), al.getHeight());
 
     /*
      * hiding a feature not present does nothing
      */
-    assertFalse(af.hideFeatureColumns("exon", true));
-    assertTrue(af.getViewport().getColumnSelection().isEmpty());
-    assertTrue(af.getViewport().getColumnSelection().getHiddenColumns()
+    assertFalse(alignFrame.hideFeatureColumns("exon", true));
+    assertTrue(alignFrame.getViewport().getColumnSelection().isEmpty());
+    assertTrue(alignFrame.getViewport().getColumnSelection().getHiddenColumns()
             .isEmpty());
-    assertFalse(af.hideFeatureColumns("exon", false));
-    assertTrue(af.getViewport().getColumnSelection().isEmpty());
-    assertTrue(af.getViewport().getColumnSelection().getHiddenColumns()
+    assertFalse(alignFrame.hideFeatureColumns("exon", false));
+    assertTrue(alignFrame.getViewport().getColumnSelection().isEmpty());
+    assertTrue(alignFrame.getViewport().getColumnSelection().getHiddenColumns()
             .isEmpty());
 
     /*
      * hiding a feature in all columns does nothing
      */
-    assertFalse(af.hideFeatureColumns("Metal", true));
-    assertTrue(af.getViewport().getColumnSelection().isEmpty());
-    List<int[]> hidden = af.getViewport().getColumnSelection()
+    assertFalse(alignFrame.hideFeatureColumns("Metal", true));
+    assertTrue(alignFrame.getViewport().getColumnSelection().isEmpty());
+    List<int[]> hidden = alignFrame.getViewport().getColumnSelection()
             .getHiddenColumns();
     assertTrue(hidden.isEmpty());
 
@@ -87,12 +106,462 @@ public class AlignFrameTest
      * sequence positions [2-4], [7-9] are column positions
      * [1-3], [6-8] base zero
      */
-    assertTrue(af.hideFeatureColumns("Turn", true));
-    hidden = af.getViewport().getColumnSelection().getHiddenColumns();
-    assertEquals(2, hidden.size());
-    assertEquals(1, hidden.get(0)[0]);
-    assertEquals(3, hidden.get(0)[1]);
-    assertEquals(6, hidden.get(1)[0]);
-    assertEquals(8, hidden.get(1)[1]);
+    assertTrue(alignFrame.hideFeatureColumns("Turn", true));
+    hidden = alignFrame.getViewport().getColumnSelection().getHiddenColumns();
+    assertEquals(hidden.size(), 2);
+    assertEquals(hidden.get(0)[0], 1);
+    assertEquals(hidden.get(0)[1], 3);
+    assertEquals(hidden.get(1)[0], 6);
+    assertEquals(hidden.get(1)[1], 8);
+  }
+
+  @BeforeClass(alwaysRun = true)
+  public static void setUpBeforeClass() throws Exception
+  {
+    /*
+     * use read-only test properties file
+     */
+    Cache.loadProperties("test/jalview/io/testProps.jvprops");
+    Jalview.main(new String[] { "-nonews" });
+  }
+
+  @AfterMethod(alwaysRun = true)
+  public void tearDown()
+  {
+    Desktop.instance.closeAll_actionPerformed(null);
+  }
+
+  /**
+   * configure (read-only) properties for test to ensure Consensus is computed
+   * for colour Above PID testing
+   */
+  @BeforeMethod(alwaysRun = true)
+  public void setUp()
+  {
+    Cache.loadProperties("test/jalview/io/testProps.jvprops");
+    Cache.applicationProperties.setProperty("SHOW_IDENTITY",
+            Boolean.TRUE.toString());
+    af = new FileLoader().LoadFileWaitTillLoaded("examples/uniref50.fa",
+            DataSourceType.FILE);
+
+    /*
+     * wait for Consensus thread to complete
+     */
+    synchronized (this)
+    {
+      while (af.getViewport().getConsensusSeq() == null)
+      {
+        try
+        {
+          wait(50);
+        } catch (InterruptedException e)
+        {
+        }
+      }
+    }
+  }
+
+  /**
+   * Test that changing background (alignment) colour scheme
+   * <ul>
+   * <li>with Apply Colour to All Groups not selected, does not change group
+   * colours</li>
+   * <li>with Apply Colour to All Groups selected, does change group colours</li>
+   * <li>in neither case, changes alignment or group colour thresholds (PID or
+   * Conservation)</li>
+   * </ul>
+   */
+  @Test(groups = "Functional")
+  public void testChangeColour_background_groupsAndThresholds()
+  {
+    AlignViewport av = af.getViewport();
+    AlignmentI al = av.getAlignment();
+
+    /*
+     * Colour alignment by Buried Index
+     */
+    af.applyToAllGroups_actionPerformed(false);
+    af.changeColour_actionPerformed(JalviewColourScheme.Buried.toString());
+    assertTrue(av.getGlobalColourScheme() instanceof BuriedColourScheme);
+    assertFalse(av.getResidueShading().conservationApplied());
+    assertEquals(av.getResidueShading().getThreshold(), 0);
+
+    /*
+     * Apply Conservation 20%
+     */
+    af.conservationMenuItem_actionPerformed(true);
+    SliderPanel sp = SliderPanel.getSliderPanel();
+    assertEquals(sp.getTitle(), MessageManager.formatMessage(
+            "label.conservation_colour_increment",
+            new String[] { "Background" }));
+    assertTrue(sp.isForConservation());
+    sp.valueChanged(20);
+    assertTrue(av.getResidueShading().conservationApplied());
+    assertEquals(av.getResidueShading().getConservationInc(), 20);
+
+    /*
+     * Apply PID threshold 10% (conservation still applies as well)
+     */
+    af.abovePIDThreshold_actionPerformed(true);
+    sp = SliderPanel.getSliderPanel();
+    assertFalse(sp.isForConservation());
+    assertEquals(sp.getTitle(), MessageManager.formatMessage(
+            "label.percentage_identity_threshold",
+            new String[] { "Background" }));
+    sp.valueChanged(10);
+    assertEquals(av.getResidueShading().getThreshold(), 10);
+    assertTrue(av.getResidueShading().conservationApplied());
+    assertEquals(av.getResidueShading().getConservationInc(), 20);
+
+    /*
+     * create a group with Strand colouring, 30% Conservation
+     * and 40% PID threshold
+     */
+    SequenceGroup sg = new SequenceGroup();
+    sg.addSequence(al.getSequenceAt(0), false);
+    sg.setStartRes(15);
+    sg.setEndRes(25);
+    av.setSelectionGroup(sg);
+
+    /*
+     * apply 30% Conservation to group
+     */
+    PopupMenu popupMenu = new PopupMenu(af.alignPanel, null, null);
+    popupMenu.changeColour_actionPerformed(JalviewColourScheme.Strand
+            .toString());
+    assertTrue(sg.getColourScheme() instanceof StrandColourScheme);
+    assertEquals(al.getGroups().size(), 1);
+    assertSame(al.getGroups().get(0), sg);
+    popupMenu.conservationMenuItem_actionPerformed(true);
+    sp = SliderPanel.getSliderPanel();
+    assertTrue(sp.isForConservation());
+    assertEquals(sp.getTitle(), MessageManager.formatMessage(
+            "label.conservation_colour_increment",
+            new String[] { sg.getName() }));
+    sp.valueChanged(30);
+    assertTrue(sg.getGroupColourScheme().conservationApplied());
+    assertEquals(sg.getGroupColourScheme().getConservationInc(), 30);
+
+    /*
+     * apply 40% PID threshold to group
+     */
+    popupMenu.abovePIDColour_actionPerformed(true);
+    sp = SliderPanel.getSliderPanel();
+    assertFalse(sp.isForConservation());
+    assertEquals(sp.getTitle(), MessageManager.formatMessage(
+            "label.percentage_identity_threshold",
+            new String[] { sg.getName() }));
+    sp.valueChanged(40);
+    assertEquals(sg.getGroupColourScheme().getThreshold(), 40);
+    // conservation threshold is unchanged:
+    assertTrue(sg.getGroupColourScheme().conservationApplied());
+    assertEquals(sg.getGroupColourScheme().getConservationInc(), 30);
+
+    /*
+     * change alignment colour - group colour, and all thresholds,
+     * should be unaffected
+     */
+    af.changeColour_actionPerformed(JalviewColourScheme.Turn.toString());
+    assertTrue(av.getGlobalColourScheme() instanceof TurnColourScheme);
+    assertTrue(av.getResidueShading().conservationApplied());
+    assertEquals(av.getResidueShading().getConservationInc(), 20);
+    assertEquals(av.getResidueShading().getThreshold(), 10);
+    assertTrue(sg.getColourScheme() instanceof StrandColourScheme);
+    assertTrue(sg.getGroupColourScheme().conservationApplied());
+    assertEquals(sg.getGroupColourScheme().getConservationInc(), 30);
+    assertEquals(sg.getGroupColourScheme().getThreshold(), 40);
+
+    /*
+     * Now change alignment colour with Apply Colour To All Groups
+     * - group colour should change, but not colour thresholds
+     */
+    af.applyToAllGroups_actionPerformed(true);
+    af.changeColour_actionPerformed(JalviewColourScheme.Helix.toString());
+    assertTrue(av.getGlobalColourScheme() instanceof HelixColourScheme);
+    assertTrue(av.getResidueShading().conservationApplied());
+    assertEquals(av.getResidueShading().getConservationInc(), 20);
+    assertEquals(av.getResidueShading().getThreshold(), 10);
+    assertTrue(sg.getColourScheme() instanceof HelixColourScheme);
+    assertTrue(sg.getGroupColourScheme().conservationApplied());
+    assertEquals(sg.getGroupColourScheme().getConservationInc(), 30);
+    assertEquals(sg.getGroupColourScheme().getThreshold(), 40);
+  }
+
+  /**
+   * Test residue colouring with various options
+   * <ol>
+   * <li>no PID or Conservation threshold</li>
+   * <li>colour by Conservation applied</li>
+   * <li>colour by Conservation removed</li>
+   * <li>colour above PID - various values</li>
+   * <li>colour above PID removed</li>
+   * <li>Above PID plus By Conservation combined</li>
+   * <li>remove Above PID to leave just By Conservation</li>
+   * <li>re-add Above PID</li>
+   * <li>remove By Conservation to leave just Above PID</li>
+   * <li>remove Above PID to leave original colours</li>
+   * </ol>
+   */
+  @Test(groups = "Functional")
+  public void testColourThresholdActions()
+  {
+    AlignViewport av = af.getViewport();
+    AlignmentI al = av.getAlignment();
+
+    /*
+     * Colour alignment by Helix Propensity, no thresholds
+     */
+    af.applyToAllGroups_actionPerformed(false);
+    af.changeColour_actionPerformed(JalviewColourScheme.Helix.toString());
+    assertTrue(av.getGlobalColourScheme() instanceof HelixColourScheme);
+    assertFalse(av.getResidueShading().conservationApplied());
+    assertEquals(av.getResidueShading().getThreshold(), 0);
+
+    /*
+     * inspect the colour of 
+     * FER_CAPAN.9(I), column 14 (14 base 0)
+     * FER_CAPAN.10(SER), column 16 (15 base 0)
+     */
+    SequenceI ferCapan = al.findName("FER_CAPAN");
+    ResidueShaderI rs = av.getResidueShading();
+    Color c = rs.findColour('I', 14, ferCapan);
+    Color i_original = new Color(138, 117, 138);
+    assertEquals(c, i_original);
+    c = rs.findColour('S', 15, ferCapan);
+    Color s_original = new Color(54, 201, 54);
+    assertEquals(c, s_original);
+
+    /*
+     * colour by conservation with increment 10
+     */
+    af.conservationMenuItem_actionPerformed(true);
+    SliderPanel sp = SliderPanel.getSliderPanel();
+    assertTrue(sp.isForConservation());
+    assertEquals(sp.getValue(), 30); // initial slider setting
+    sp.valueChanged(10);
+    assertSame(rs, av.getResidueShading());
+    c = rs.findColour('I', 14, ferCapan);
+    Color i_faded = new Color(196, 186, 196);
+    assertEquals(c, i_faded);
+    c = rs.findColour('S', 15, ferCapan);
+    Color s_faded = new Color(144, 225, 144);
+    assertEquals(c, s_faded);
+
+    /*
+     * deselect By Conservation - colour should revert
+     */
+    af.conservationMenuItem_actionPerformed(false);
+    c = rs.findColour('S', 15, ferCapan);
+    assertEquals(c, s_original);
+
+    /*
+     * now Above PID, threshold = 0%
+     * should be no change
+     */
+    af.abovePIDThreshold_actionPerformed(true);
+    sp = SliderPanel.getSliderPanel();
+    assertFalse(sp.isForConservation());
+    assertEquals(sp.getValue(), 0); // initial slider setting
+    c = rs.findColour('I', 14, ferCapan);
+    assertEquals(c, i_original);
+    c = rs.findColour('S', 15, ferCapan);
+    assertEquals(c, s_original);
+
+    /*
+     * Above PID, threshold = 1%
+     * 15.I becomes White because no match to consensus (V)
+     * 16.S remains coloured as matches 66.66% consensus
+     */
+    sp.valueChanged(1);
+    c = rs.findColour('I', 14, ferCapan);
+    assertEquals(c, Color.white);
+    c = rs.findColour('S', 15, ferCapan);
+    assertEquals(c, s_original);
+
+    /*
+     * threshold 66% - no further change yet...
+     */
+    sp.valueChanged(66);
+    c = rs.findColour('I', 14, ferCapan);
+    assertEquals(c, Color.white);
+    c = rs.findColour('S', 15, ferCapan);
+    assertEquals(c, s_original);
+
+    /*
+     * threshold 67% - now both residues are white
+     */
+    sp.valueChanged(67);
+    c = rs.findColour('I', 14, ferCapan);
+    assertEquals(c, Color.white);
+    c = rs.findColour('S', 15, ferCapan);
+    assertEquals(c, Color.white);
+
+    /*
+     * deselect Above PID - colours should revert
+     */
+    af.abovePIDThreshold_actionPerformed(false);
+    c = rs.findColour('I', 14, ferCapan);
+    assertEquals(c, i_original);
+    c = rs.findColour('S', 15, ferCapan);
+    assertEquals(c, s_original);
+
+    /*
+     * Now combine Above 50% PID and By Conservation 10%
+     * 15.I is White because no match to consensus (V)
+     * 16.S is coloured but faded
+     */
+    af.abovePIDThreshold_actionPerformed(true);
+    sp = SliderPanel.getSliderPanel();
+    assertFalse(sp.isForConservation());
+    sp.valueChanged(50);
+    af.conservationMenuItem_actionPerformed(true);
+    sp = SliderPanel.getSliderPanel();
+    assertTrue(sp.isForConservation());
+    sp.valueChanged(10);
+    c = rs.findColour('I', 14, ferCapan);
+    assertEquals(c, Color.white);
+    c = rs.findColour('S', 15, ferCapan);
+    assertEquals(c, s_faded);
+
+    /*
+     * turn off Above PID - should just leave Conservation fading as before 
+     */
+    af.abovePIDThreshold_actionPerformed(false);
+    c = rs.findColour('I', 14, ferCapan);
+    assertEquals(c, i_faded);
+    c = rs.findColour('S', 15, ferCapan);
+    assertEquals(c, s_faded);
+
+    /*
+     * Now add Above 50% PID to conservation colouring
+     * - should give the same as PID followed by conservation (above)
+     */
+    af.abovePIDThreshold_actionPerformed(true);
+    SliderPanel.getSliderPanel().valueChanged(50);
+    c = rs.findColour('I', 14, ferCapan);
+    assertEquals(c, Color.white);
+    c = rs.findColour('S', 15, ferCapan);
+    assertEquals(c, s_faded);
+
+    /*
+     * turn off By Conservation
+     * should leave I white, S original (unfaded) colour
+     */
+    af.conservationMenuItem_actionPerformed(false);
+    c = rs.findColour('I', 14, ferCapan);
+    assertEquals(c, Color.white);
+    c = rs.findColour('S', 15, ferCapan);
+    assertEquals(c, s_original);
+
+    /*
+     * finally turn off Above PID to leave original colours
+     */
+    af.abovePIDThreshold_actionPerformed(false);
+    c = rs.findColour('I', 14, ferCapan);
+    assertEquals(c, i_original);
+    c = rs.findColour('S', 15, ferCapan);
+    assertEquals(c, s_original);
+  }
+
+  /**
+   * Verify that making a New View transfers alignment and group colour schemes,
+   * including any thresholds, to the new view. Because New View is performed by
+   * saving and reloading a 'project' file, this is similar to verifying a
+   * project save and reload.
+   * 
+   * @see Jalview2xmlTests#testStoreAndRecoverColourThresholds()
+   */
+  @Test(groups = "Functional")
+  public void testNewView_colourThresholds()
+  {
+    AlignViewport av = af.getViewport();
+    AlignmentI al = av.getAlignment();
+
+    /*
+     * Colour alignment by Buried Index, Above 10% PID, By Conservation 20%
+     */
+    af.changeColour_actionPerformed(JalviewColourScheme.Buried.toString());
+    assertTrue(av.getGlobalColourScheme() instanceof BuriedColourScheme);
+    af.abovePIDThreshold_actionPerformed(true);
+    SliderPanel sp = SliderPanel.getSliderPanel();
+    assertFalse(sp.isForConservation());
+    sp.valueChanged(10);
+    af.conservationMenuItem_actionPerformed(true);
+    sp = SliderPanel.getSliderPanel();
+    assertTrue(sp.isForConservation());
+    sp.valueChanged(20);
+    ResidueShaderI rs = av.getResidueShading();
+    assertEquals(rs.getThreshold(), 10);
+    assertTrue(rs.conservationApplied());
+    assertEquals(rs.getConservationInc(), 20);
+
+    /*
+     * create a group with Strand colouring, 30% Conservation
+     * and 40% PID threshold
+     */
+    SequenceGroup sg = new SequenceGroup();
+    sg.addSequence(al.getSequenceAt(0), false);
+    sg.setStartRes(15);
+    sg.setEndRes(25);
+    av.setSelectionGroup(sg);
+    PopupMenu popupMenu = new PopupMenu(af.alignPanel, null, null);
+    popupMenu.changeColour_actionPerformed(JalviewColourScheme.Strand
+            .toString());
+    assertTrue(sg.getColourScheme() instanceof StrandColourScheme);
+    assertEquals(al.getGroups().size(), 1);
+    assertSame(al.getGroups().get(0), sg);
+    popupMenu.conservationMenuItem_actionPerformed(true);
+    sp = SliderPanel.getSliderPanel();
+    assertTrue(sp.isForConservation());
+    sp.valueChanged(30);
+    popupMenu.abovePIDColour_actionPerformed(true);
+    sp = SliderPanel.getSliderPanel();
+    assertFalse(sp.isForConservation());
+    sp.valueChanged(40);
+    rs = sg.getGroupColourScheme();
+    assertTrue(rs.conservationApplied());
+    assertEquals(rs.getConservationInc(), 30);
+    assertEquals(rs.getThreshold(), 40);
+
+    /*
+     * set slider panel focus to the background alignment
+     */
+    af.conservationMenuItem_actionPerformed(true);
+    sp = SliderPanel.getSliderPanel();
+    assertTrue(sp.isForConservation());
+    assertEquals(sp.getTitle(), MessageManager.formatMessage(
+            "label.conservation_colour_increment",
+            new String[] { "Background" }));
+
+    /*
+     * make a new View, verify alignment and group colour schemes
+     */
+    af.newView_actionPerformed(null);
+    assertEquals(af.alignPanel.getViewName(), "View 1");
+    AlignViewport av2 = af.getViewport();
+    assertNotSame(av, av2);
+    rs = av2.getResidueShading();
+    assertNotSame(av.getResidueShading(), rs);
+    assertEquals(rs.getThreshold(), 10);
+    assertTrue(rs.conservationApplied());
+    assertEquals(rs.getConservationInc(), 20);
+    assertEquals(av2.getAlignment().getGroups().size(), 1);
+    sg = av2.getAlignment().getGroups().get(0);
+    rs = sg.getGroupColourScheme();
+    assertTrue(rs.conservationApplied());
+    assertEquals(rs.getConservationInc(), 30);
+    assertEquals(rs.getThreshold(), 40);
+
+    /*
+     * check the Conservation SliderPanel (still open) is linked to 
+     * and updates the new view (JAL-2385)
+     */
+    sp = SliderPanel.getSliderPanel();
+    assertTrue(sp.isForConservation());
+    assertEquals(sp.getTitle(), MessageManager.formatMessage(
+            "label.conservation_colour_increment",
+            new String[] { "View 1" }));
+    sp.valueChanged(22);
+    assertEquals(av2.getResidueShading().getConservationInc(), 22);
   }
 }
index 5695b15..06df70a 100644 (file)
@@ -38,6 +38,7 @@ import jalview.datamodel.PDBEntry.Type;
 import jalview.datamodel.SearchResults;
 import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.io.DataSourceType;
 import jalview.io.FileLoader;
@@ -70,7 +71,8 @@ public class AlignViewportTest
   @BeforeClass(alwaysRun = true)
   public static void setUpBeforeClass() throws Exception
   {
-    Jalview.main(new String[] { "-props", "test/jalview/testProps.jvprops" });
+    Jalview.main(new String[] { "-nonews", "-props",
+        "test/jalview/testProps.jvprops" });
   }
 
   @BeforeMethod(alwaysRun = true)
@@ -345,16 +347,17 @@ public class AlignViewportTest
   public void testSetGlobalColourScheme()
   {
     /*
-     * test for JAL-2283 don't inadvertently turn on colour by conservation
+     * test for JAL-2283: don't inadvertently turn on colour by conservation
      */
-    Cache.applicationProperties.setProperty("DEFAULT_COLOUR_PROT", "NONE");
+    Cache.applicationProperties.setProperty("DEFAULT_COLOUR_PROT", "None");
     Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
             Boolean.TRUE.toString());
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
             "examples/uniref50.fa", DataSourceType.FILE);
     ColourSchemeI cs = new PIDColourScheme();
     af.getViewport().setGlobalColourScheme(cs);
-    assertFalse(cs.conservationApplied());
+    assertFalse(af.getViewport().getResidueShading()
+            .conservationApplied());
   }
 
   @Test(groups = { "Functional" })
@@ -380,4 +383,25 @@ public class AlignViewportTest
     af.getViewport().setSearchResults(null);
     assertFalse(af.getViewport().hasSearchResults());
   }
+
+  /**
+   * Verify that setting the selection group has the side-effect of setting the
+   * context on the group, unless it already has one
+   */
+  @Test(groups = { "Functional" })
+  public void testSetSelectionGroup()
+  {
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", DataSourceType.FILE);
+    AlignViewport av = af.getViewport();
+    SequenceGroup sg1 = new SequenceGroup();
+    SequenceGroup sg2 = new SequenceGroup();
+
+    av.setSelectionGroup(sg1);
+    assertSame(sg1.getContext(), av.getAlignment()); // context set
+
+    sg2.setContext(sg1);
+    av.setSelectionGroup(sg2);
+    assertSame(sg2.getContext(), sg1); // unchanged
+  }
 }
index 922d457..335240b 100644 (file)
@@ -321,7 +321,8 @@ public class PopupMenuTest
 
     assertEquals(4, showOptions.length); // includes 'All' and separator
     assertEquals(4, hideOptions.length);
-    assertEquals("All", ((JMenuItem) showOptions[0]).getText());
+    String all = MessageManager.getString("label.all");
+    assertEquals(all, ((JMenuItem) showOptions[0]).getText());
     assertTrue(showOptions[1] instanceof JPopupMenu.Separator);
     assertEquals(JSeparator.HORIZONTAL,
             ((JSeparator) showOptions[1]).getOrientation());
@@ -331,7 +332,7 @@ public class PopupMenuTest
     assertEquals("SSP", ((JMenuItem) showOptions[3]).getText());
     assertEquals("JPred", ((JMenuItem) showOptions[3]).getToolTipText());
 
-    assertEquals("All", ((JMenuItem) hideOptions[0]).getText());
+    assertEquals(all, ((JMenuItem) hideOptions[0]).getText());
     assertTrue(hideOptions[1] instanceof JPopupMenu.Separator);
     assertEquals(JSeparator.HORIZONTAL,
             ((JSeparator) hideOptions[1]).getOrientation());
@@ -383,12 +384,13 @@ public class PopupMenuTest
 
     assertEquals(2, showOptions.length); // includes 'All' and separator
     assertEquals(4, hideOptions.length);
-    assertEquals("All", ((JMenuItem) showOptions[0]).getText());
+    String all = MessageManager.getString("label.all");
+    assertEquals(all, ((JMenuItem) showOptions[0]).getText());
     assertTrue(showOptions[1] instanceof JPopupMenu.Separator);
     assertEquals(JSeparator.HORIZONTAL,
             ((JSeparator) showOptions[1]).getOrientation());
 
-    assertEquals("All", ((JMenuItem) hideOptions[0]).getText());
+    assertEquals(all, ((JMenuItem) hideOptions[0]).getText());
     assertTrue(hideOptions[1] instanceof JPopupMenu.Separator);
     assertEquals(JSeparator.HORIZONTAL,
             ((JSeparator) hideOptions[1]).getOrientation());
@@ -440,7 +442,8 @@ public class PopupMenuTest
 
     assertEquals(4, showOptions.length); // includes 'All' and separator
     assertEquals(2, hideOptions.length);
-    assertEquals("All", ((JMenuItem) showOptions[0]).getText());
+    String all = MessageManager.getString("label.all");
+    assertEquals(all, ((JMenuItem) showOptions[0]).getText());
     assertTrue(showOptions[1] instanceof JPopupMenu.Separator);
     assertEquals(JSeparator.HORIZONTAL,
             ((JSeparator) showOptions[1]).getOrientation());
@@ -450,7 +453,7 @@ public class PopupMenuTest
     assertEquals("Temp", ((JMenuItem) showOptions[3]).getText());
     assertEquals("PDB2", ((JMenuItem) showOptions[3]).getToolTipText());
 
-    assertEquals("All", ((JMenuItem) hideOptions[0]).getText());
+    assertEquals(all, ((JMenuItem) hideOptions[0]).getText());
     assertTrue(hideOptions[1] instanceof JPopupMenu.Separator);
     assertEquals(JSeparator.HORIZONTAL,
             ((JSeparator) hideOptions[1]).getOrientation());
index 5b90e19..885c673 100644 (file)
@@ -70,7 +70,7 @@ public class AnnotationFileIOTest
     }
   }
 
-  public static AlignmentI readAlignmentFile(File f)
+  AlignmentI readAlignmentFile(File f)
   {
     System.out.println("Reading file: " + f);
     String ff = f.getPath();
@@ -106,9 +106,7 @@ public class AnnotationFileIOTest
    *          - label for IO class used to write and read back in the data from
    *          f
    */
-
-  // @Test(groups ={ "Functional" })
-  public static void testAnnotationFileIO(String testname, File f,
+  void testAnnotationFileIO(String testname, File f,
           File annotFile)
   {
     System.out.println("Test: " + testname + "\nReading annotation file '"
index ffc844c..7810504 100644 (file)
@@ -10,16 +10,23 @@ import static org.testng.Assert.assertTrue;
 import java.util.Iterator;
 
 import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 public class FileFormatsTest
 {
-  @AfterMethod()
+  @AfterMethod(alwaysRun = true)
   public void tearDown()
   {
     FileFormats.getInstance().reset();
   }
 
+  @BeforeMethod(alwaysRun = true)
+  public void setUp()
+  {
+    FileFormats.getInstance().reset();
+  }
+
   @Test(groups = "Functional")
   public void testIsIdentifiable()
   {
index a705a78..a8611cc 100644 (file)
@@ -137,7 +137,7 @@ public class JSONFileTest
             null, true, true, false, 21, 29);
     ColourSchemeI scheme = ColourSchemeMapper.getJalviewColourScheme(
             "zappo", seqGrp);
-    seqGrp.cs = scheme;
+    seqGrp.cs.setColourScheme(scheme);
     seqGrp.setShowNonconserved(false);
     seqGrp.setDescription(null);
 
index de12086..6abb7e5 100644 (file)
  */
 package jalview.io;
 
-import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertFalse;
-import static org.testng.AssertJUnit.assertNotNull;
-import static org.testng.AssertJUnit.assertSame;
-import static org.testng.AssertJUnit.assertTrue;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
 
 import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
@@ -38,18 +38,27 @@ import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
+import jalview.gui.AlignViewport;
 import jalview.gui.AlignmentPanel;
 import jalview.gui.Desktop;
 import jalview.gui.Jalview2XML;
 import jalview.gui.JvOptionPane;
+import jalview.gui.PopupMenu;
+import jalview.gui.SliderPanel;
+import jalview.renderer.ResidueShaderI;
 import jalview.schemes.AnnotationColourGradient;
+import jalview.schemes.BuriedColourScheme;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemeProperty;
+import jalview.schemes.JalviewColourScheme;
+import jalview.schemes.RNAHelicesColour;
+import jalview.schemes.StrandColourScheme;
 import jalview.schemes.TCoffeeColourScheme;
 import jalview.structure.StructureImportSettings;
 import jalview.viewmodel.AlignmentViewport;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -64,6 +73,7 @@ import org.testng.annotations.Test;
 public class Jalview2xmlTests extends Jalview2xmlBase
 {
 
+  @Override
   @BeforeClass(alwaysRun = true)
   public void setUpJvOptionPane()
   {
@@ -77,32 +87,34 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     String inFile = "examples/RF00031_folded.stk";
     String tfile = File.createTempFile("JalviewTest", ".jvp")
             .getAbsolutePath();
-    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
-            inFile, DataSourceType.FILE);
-    assertTrue("Didn't read input file " + inFile, af != null);
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(inFile,
+            DataSourceType.FILE);
+    assertNotNull(af, "Didn't read input file " + inFile);
     int olddsann = countDsAnn(af.getViewport());
-    assertTrue("Didn't find any dataset annotations", olddsann > 0);
-    af.rnahelicesColour_actionPerformed(null);
+    assertTrue(olddsann > 0, "Didn't find any dataset annotations");
+    af.changeColour_actionPerformed(JalviewColourScheme.RNAHelices
+            .toString());
     assertTrue(
-            "Couldn't apply RNA helices colourscheme",
-            af.getViewport().getGlobalColourScheme() instanceof jalview.schemes.RNAHelicesColour);
-    assertTrue("Failed to store as a project.",
-            af.saveAlignment(tfile, FileFormat.Jalview));
+            af.getViewport().getGlobalColourScheme() instanceof RNAHelicesColour,
+            "Couldn't apply RNA helices colourscheme");
+    assertTrue(af.saveAlignment(tfile, FileFormat.Jalview),
+            "Failed to store as a project.");
     af.closeMenuItem_actionPerformed(true);
     af = null;
-    af = new FileLoader().LoadFileWaitTillLoaded(tfile, DataSourceType.FILE);
-    assertTrue("Failed to import new project", af != null);
+    af = new FileLoader()
+            .LoadFileWaitTillLoaded(tfile, DataSourceType.FILE);
+    assertNotNull(af, "Failed to import new project");
     int newdsann = countDsAnn(af.getViewport());
-    assertTrue(
+    assertEquals(olddsann, newdsann,
             "Differing numbers of dataset sequence annotation\nOriginally "
-                    + olddsann + " and now " + newdsann,
-            olddsann == newdsann);
+                    + olddsann + " and now " + newdsann);
     System.out
             .println("Read in same number of annotations as originally present ("
                     + olddsann + ")");
     assertTrue(
-            "RNA helices colourscheme was not applied on import.",
-            af.getViewport().getGlobalColourScheme() instanceof jalview.schemes.RNAHelicesColour);
+
+    af.getViewport().getGlobalColourScheme() instanceof RNAHelicesColour,
+            "RNA helices colourscheme was not applied on import.");
   }
 
   @Test(groups = { "Functional" })
@@ -111,27 +123,26 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     String inFile = "examples/uniref50.fa", inAnnot = "examples/uniref50.score_ascii";
     String tfile = File.createTempFile("JalviewTest", ".jvp")
             .getAbsolutePath();
-    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
-            inFile, DataSourceType.FILE);
-    assertNotNull("Didn't read input file " + inFile, af);
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(inFile,
+            DataSourceType.FILE);
+    assertNotNull(af, "Didn't read input file " + inFile);
     af.loadJalviewDataFile(inAnnot, DataSourceType.FILE, null, null);
-    assertSame("Didn't set T-coffee colourscheme", af.getViewport()
-            .getGlobalColourScheme().getClass(), TCoffeeColourScheme.class);
-    assertNotNull("Recognise T-Coffee score from string",
-            ColourSchemeProperty.getColour(af.getViewport()
-                    .getAlignment(), ColourSchemeProperty.getColourName(af
-                    .getViewport().getGlobalColourScheme())));
-
-    assertTrue("Failed to store as a project.",
-            af.saveAlignment(tfile, FileFormat.Jalview));
+    assertSame(af.getViewport().getGlobalColourScheme().getClass(),
+            TCoffeeColourScheme.class, "Didn't set T-coffee colourscheme");
+    assertNotNull(ColourSchemeProperty.getColourScheme(af.getViewport()
+            .getAlignment(), af.getViewport().getGlobalColourScheme()
+            .getSchemeName()), "Recognise T-Coffee score from string");
+
+    assertTrue(af.saveAlignment(tfile, FileFormat.Jalview),
+            "Failed to store as a project.");
     af.closeMenuItem_actionPerformed(true);
     af = null;
-    af = new FileLoader().LoadFileWaitTillLoaded(tfile,
-            DataSourceType.FILE);
-    assertNotNull("Failed to import new project", af);
-    assertSame("Didn't set T-coffee colourscheme for imported project.", af
-            .getViewport().getGlobalColourScheme().getClass(),
-            TCoffeeColourScheme.class);
+    af = new FileLoader()
+            .LoadFileWaitTillLoaded(tfile, DataSourceType.FILE);
+    assertNotNull(af, "Failed to import new project");
+    assertSame(af.getViewport().getGlobalColourScheme().getClass(),
+            TCoffeeColourScheme.class,
+            "Didn't set T-coffee colourscheme for imported project.");
     System.out
             .println("T-Coffee score shading successfully recovered from project.");
   }
@@ -142,14 +153,16 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     String inFile = "examples/uniref50.fa", inAnnot = "examples/testdata/uniref50_iupred.jva";
     String tfile = File.createTempFile("JalviewTest", ".jvp")
             .getAbsolutePath();
-    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(inFile, DataSourceType.FILE);
-    assertNotNull("Didn't read input file " + inFile, af);
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(inFile,
+            DataSourceType.FILE);
+    assertNotNull(af, "Didn't read input file " + inFile);
     af.loadJalviewDataFile(inAnnot, DataSourceType.FILE, null, null);
     AlignmentAnnotation[] aa = af.getViewport().getAlignment()
             .getSequenceAt(0).getAnnotation("IUPredWS (Short)");
     assertTrue(
-            "Didn't find any IUPred annotation to use to shade alignment.",
-            aa != null && aa.length > 0);
+
+    aa != null && aa.length > 0,
+            "Didn't find any IUPred annotation to use to shade alignment.");
     AnnotationColourGradient cs = new AnnotationColourGradient(aa[0], null,
             AnnotationColourGradient.ABOVE_THRESHOLD);
     AnnotationColourGradient gcs = new AnnotationColourGradient(aa[0],
@@ -160,62 +173,63 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     SequenceGroup sg = new SequenceGroup();
     sg.setStartRes(57);
     sg.setEndRes(92);
-    sg.cs = gcs;
+    sg.cs.setColourScheme(gcs);
     af.getViewport().getAlignment().addGroup(sg);
     sg.addSequence(af.getViewport().getAlignment().getSequenceAt(1), false);
     sg.addSequence(af.getViewport().getAlignment().getSequenceAt(2), true);
     af.alignPanel.alignmentChanged();
-    assertTrue("Failed to store as a project.",
-            af.saveAlignment(tfile, FileFormat.Jalview));
+    assertTrue(af.saveAlignment(tfile, FileFormat.Jalview),
+            "Failed to store as a project.");
     af.closeMenuItem_actionPerformed(true);
     af = null;
-    af = new FileLoader().LoadFileWaitTillLoaded(tfile, DataSourceType.FILE);
-    assertTrue("Failed to import new project", af != null);
+    af = new FileLoader()
+            .LoadFileWaitTillLoaded(tfile, DataSourceType.FILE);
+    assertNotNull(af, "Failed to import new project");
 
     // check for group and alignment colourschemes
 
     ColourSchemeI _rcs = af.getViewport().getGlobalColourScheme();
     ColourSchemeI _rgcs = af.getViewport().getAlignment().getGroups()
-            .get(0).cs;
-    assertNotNull("Didn't recover global colourscheme", _rcs);
-    assertTrue("Didn't recover annotation colour global scheme",
-            _rcs instanceof AnnotationColourGradient);
+            .get(0).getColourScheme();
+    assertNotNull(_rcs, "Didn't recover global colourscheme");
+    assertTrue(_rcs instanceof AnnotationColourGradient,
+            "Didn't recover annotation colour global scheme");
     AnnotationColourGradient __rcs = (AnnotationColourGradient) _rcs;
-    assertTrue("Annotation colourscheme wasn't sequence associated",
-            __rcs.isSeqAssociated());
+    assertTrue(__rcs.isSeqAssociated(),
+            "Annotation colourscheme wasn't sequence associated");
 
     boolean diffseqcols = false, diffgseqcols = false;
     SequenceI[] sqs = af.getViewport().getAlignment().getSequencesArray();
     for (int p = 0, pSize = af.getViewport().getAlignment().getWidth(); p < pSize
             && (!diffseqcols || !diffgseqcols); p++)
     {
-      if (_rcs.findColour(sqs[0].getCharAt(p), p, sqs[0]) != _rcs
-              .findColour(sqs[5].getCharAt(p), p, sqs[5]))
+      if (_rcs.findColour(sqs[0].getCharAt(p), p, sqs[0], null, 0f) != _rcs
+              .findColour(sqs[5].getCharAt(p), p, sqs[5], null, 0f))
       {
         diffseqcols = true;
       }
     }
-    assertTrue("Got Different sequence colours", diffseqcols);
+    assertTrue(diffseqcols, "Got Different sequence colours");
     System.out
             .println("Per sequence colourscheme (Background) successfully applied and recovered.");
 
-    assertNotNull("Didn't recover group colourscheme", _rgcs);
-    assertTrue("Didn't recover annotation colour group colourscheme",
-            _rgcs instanceof AnnotationColourGradient);
+    assertNotNull(_rgcs, "Didn't recover group colourscheme");
+    assertTrue(_rgcs instanceof AnnotationColourGradient,
+            "Didn't recover annotation colour group colourscheme");
     __rcs = (AnnotationColourGradient) _rgcs;
-    assertTrue("Group Annotation colourscheme wasn't sequence associated",
-            __rcs.isSeqAssociated());
+    assertTrue(__rcs.isSeqAssociated(),
+            "Group Annotation colourscheme wasn't sequence associated");
 
     for (int p = 0, pSize = af.getViewport().getAlignment().getWidth(); p < pSize
             && (!diffseqcols || !diffgseqcols); p++)
     {
-      if (_rgcs.findColour(sqs[1].getCharAt(p), p, sqs[1]) != _rgcs
-              .findColour(sqs[2].getCharAt(p), p, sqs[2]))
+      if (_rgcs.findColour(sqs[1].getCharAt(p), p, sqs[1], null, 0f) != _rgcs
+              .findColour(sqs[2].getCharAt(p), p, sqs[2], null, 0f))
       {
         diffgseqcols = true;
       }
     }
-    assertTrue("Got Different group sequence colours", diffgseqcols);
+    assertTrue(diffgseqcols, "Got Different group sequence colours");
     System.out
             .println("Per sequence (Group) colourscheme successfully applied and recovered.");
   }
@@ -227,9 +241,9 @@ public class Jalview2xmlTests extends Jalview2xmlBase
             .getAlignFrames().length;
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
             "examples/exampleFile_2_7.jar", DataSourceType.FILE);
-    assertNotNull("Didn't read in the example file correctly.", af);
-    assertTrue("Didn't gather the views in the example file.",
-            Desktop.getAlignFrames().length == 1 + origCount);
+    assertNotNull(af, "Didn't read in the example file correctly.");
+    assertTrue(Desktop.getAlignFrames().length == 1 + origCount,
+            "Didn't gather the views in the example file.");
 
   }
 
@@ -240,7 +254,7 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     StructureImportSettings.setVisibleChainAnnotation(true);
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
             "examples/exampleFile_2_7.jar", DataSourceType.FILE);
-    assertNotNull("Didn't read in the example file correctly.", af);
+    assertNotNull(af, "Didn't read in the example file correctly.");
     AlignmentViewPanel sps = null;
     for (AlignmentViewPanel ap : af.alignPanel.alignFrame.getAlignPanels())
     {
@@ -250,7 +264,7 @@ public class Jalview2xmlTests extends Jalview2xmlBase
         break;
       }
     }
-    assertNotNull("Couldn't find the structure view", sps);
+    assertNotNull(sps, "Couldn't find the structure view");
     AlignmentAnnotation refan = null;
     for (AlignmentAnnotation ra : sps.getAlignment()
             .getAlignmentAnnotation())
@@ -261,13 +275,13 @@ public class Jalview2xmlTests extends Jalview2xmlBase
         break;
       }
     }
-    assertNotNull("Annotation secondary structure not found.", refan);
+    assertNotNull(refan, "Annotation secondary structure not found.");
     SequenceI sq = sps.getAlignment().findName("1A70|");
-    assertNotNull("Couldn't find 1a70 null chain", sq);
+    assertNotNull(sq, "Couldn't find 1a70 null chain");
     // compare the manually added temperature factor annotation
     // to the track automatically transferred from the pdb structure on load
-    assertNotNull("1a70 has no annotation", sq.getDatasetSequence()
-            .getAnnotation());
+    assertNotNull(sq.getDatasetSequence().getAnnotation(),
+            "1a70 has no annotation");
     for (AlignmentAnnotation ala : sq.getDatasetSequence().getAnnotation())
     {
       AlignmentAnnotation alaa;
@@ -281,9 +295,9 @@ public class Jalview2xmlTests extends Jalview2xmlBase
           try
           {
             assertTrue(
-                    "Mismatch at alignment position " + p,
                     (alaa.annotations[p] == null && refan.annotations[p] == null)
-                            || alaa.annotations[p].value == refan.annotations[p].value);
+                            || alaa.annotations[p].value == refan.annotations[p].value,
+                    "Mismatch at alignment position " + p);
           } catch (NullPointerException q)
           {
             Assert.fail("Mismatch of alignment annotations at position "
@@ -301,7 +315,7 @@ public class Jalview2xmlTests extends Jalview2xmlBase
   {
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
             "examples/exampleFile_2_7.jar", DataSourceType.FILE);
-    assertNotNull("Didn't read in the example file correctly.", af);
+    assertNotNull(af, "Didn't read in the example file correctly.");
     AlignmentViewPanel sps = null, groups = null;
     for (AlignmentViewPanel ap : af.alignPanel.alignFrame.getAlignPanels())
     {
@@ -314,8 +328,8 @@ public class Jalview2xmlTests extends Jalview2xmlBase
         groups = ap;
       }
     }
-    assertNotNull("Couldn't find the structure view", sps);
-    assertNotNull("Couldn't find the MAFFT view", groups);
+    assertNotNull(sps, "Couldn't find the structure view");
+    assertNotNull(groups, "Couldn't find the MAFFT view");
 
     ViewStyleI structureStyle = sps.getAlignViewport().getViewStyle();
     ViewStyleI groupStyle = groups.getAlignViewport().getViewStyle();
@@ -346,9 +360,10 @@ public class Jalview2xmlTests extends Jalview2xmlBase
 
     // check FileLoader returned a reference to the one alignFrame that is
     // actually on the Desktop
-    assertTrue(
-            "Jalview2XML.loadAlignFrame() didn't return correct AlignFrame reference for multiple view window",
-            af == Desktop.getAlignFrameFor(af.getViewport()));
+    assertSame(
+            af,
+            Desktop.getAlignFrameFor(af.getViewport()),
+            "Jalview2XML.loadAlignFrame() didn't return correct AlignFrame reference for multiple view window");
 
     Desktop.explodeViews(af);
 
@@ -371,15 +386,15 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     {
       Assert.assertEquals(Desktop.getAlignFrames().length, 0);
     }
-    af = new FileLoader().LoadFileWaitTillLoaded(
-            tfile.getAbsolutePath(), DataSourceType.FILE);
+    af = new FileLoader().LoadFileWaitTillLoaded(tfile.getAbsolutePath(),
+            DataSourceType.FILE);
     Assert.assertNotNull(af);
     Assert.assertEquals(
             Desktop.getAlignFrames().length,
             Desktop.getAlignmentPanels(af.getViewport().getSequenceSetId()).length);
     Assert.assertEquals(
-            oldviews,
-            Desktop.getAlignmentPanels(af.getViewport().getSequenceSetId()).length);
+            Desktop.getAlignmentPanels(af.getViewport().getSequenceSetId()).length,
+            oldviews);
   }
 
   /**
@@ -394,7 +409,7 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     Desktop.instance.closeAll_actionPerformed(null);
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
             "examples/exampleFile_2_7.jar", DataSourceType.FILE);
-    assertNotNull("Didn't read in the example file correctly.", af);
+    assertNotNull(af, "Didn't read in the example file correctly.");
     String afid = af.getViewport().getSequenceSetId();
 
     // remember reference sequence for each panel
@@ -436,8 +451,8 @@ public class Jalview2xmlTests extends Jalview2xmlBase
       Assert.assertEquals(Desktop.getAlignFrames().length, 0);
     }
 
-    af = new FileLoader().LoadFileWaitTillLoaded(
-            tfile.getAbsolutePath(), DataSourceType.FILE);
+    af = new FileLoader().LoadFileWaitTillLoaded(tfile.getAbsolutePath(),
+            DataSourceType.FILE);
     afid = af.getViewport().getSequenceSetId();
 
     for (AlignmentViewPanel ap : Desktop.getAlignmentPanels(afid))
@@ -527,7 +542,7 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     Desktop.instance.closeAll_actionPerformed(null);
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
             "examples/uniref50.fa", DataSourceType.FILE);
-    assertNotNull("Didn't read in the example file correctly.", af);
+    assertNotNull(af, "Didn't read in the example file correctly.");
     String afid = af.getViewport().getSequenceSetId();
     // make a second view of the alignment
     af.newView_actionPerformed(null);
@@ -578,7 +593,7 @@ public class Jalview2xmlTests extends Jalview2xmlBase
       assertSame(repSeq, sg.getSeqrep());
       assertTrue(sg.getSequences().contains(repSeq));
       assertTrue(sg.getSequences().contains(precedingSeq));
-      assertTrue("alignment has groups", alignment.getGroups().isEmpty());
+      assertTrue(alignment.getGroups().isEmpty(), "alignment has groups");
       Map<SequenceI, SequenceCollectionI> hiddenRepSeqsMap = av
               .getHiddenRepSequences();
       assertNotNull(hiddenRepSeqsMap);
@@ -604,9 +619,9 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     {
       Assert.assertEquals(Desktop.getAlignFrames().length, 0);
     }
-  
-    af = new FileLoader().LoadFileWaitTillLoaded(
-            tfile.getAbsolutePath(), DataSourceType.FILE);
+
+    af = new FileLoader().LoadFileWaitTillLoaded(tfile.getAbsolutePath(),
+            DataSourceType.FILE);
     afid = af.getViewport().getSequenceSetId();
 
     for (AlignmentViewPanel ap : Desktop.getAlignmentPanels(afid))
@@ -616,10 +631,10 @@ public class Jalview2xmlTests extends Jalview2xmlBase
       AlignmentI alignment = ap.getAlignment();
       List<SequenceGroup> groups = alignment.getGroups();
       assertNotNull(groups);
-      assertTrue("Alignment has groups", groups.isEmpty());
+      assertTrue(groups.isEmpty(), "Alignment has groups");
       Map<SequenceI, SequenceCollectionI> hiddenRepSeqsMap = av
               .getHiddenRepSequences();
-      assertNotNull("No hidden represented sequences", hiddenRepSeqsMap);
+      assertNotNull(hiddenRepSeqsMap, "No hidden represented sequences");
       assertEquals(1, hiddenRepSeqsMap.size());
       assertEquals(repSeqs.get(viewName).getDisplayId(true),
               hiddenRepSeqsMap.keySet().iterator().next()
@@ -631,8 +646,10 @@ public class Jalview2xmlTests extends Jalview2xmlBase
       List<String> hidden = hiddenSeqNames.get(ap.getViewName());
       HiddenSequences hs = alignment.getHiddenSequences();
       assertEquals(
+              hidden.size(),
+              hs.getSize(),
               "wrong number of restored hidden sequences in "
-                      + ap.getViewName(), hidden.size(), hs.getSize());
+                      + ap.getViewName());
     }
   }
 
@@ -648,7 +665,7 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     String exampleFile = "examples/3W5V.pdb";
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(exampleFile,
             DataSourceType.FILE);
-    assertNotNull("Didn't read in the example file correctly.", af);
+    assertNotNull(af, "Didn't read in the example file correctly.");
     String afid = af.getViewport().getSequenceSetId();
 
     AlignmentPanel[] alignPanels = Desktop.getAlignmentPanels(afid);
@@ -729,4 +746,99 @@ public class Jalview2xmlTests extends Jalview2xmlBase
               "Recovered PDBEntry should have a non-null file entry");
     }
   }
+
+  /**
+   * Configure an alignment and a sub-group each with distinct colour schemes,
+   * Conservation and PID thresholds, and confirm these are restored from the
+   * saved project.
+   * 
+   * @throws IOException
+   */
+  @Test(groups = { "Functional" })
+  public void testStoreAndRecoverColourThresholds() throws IOException
+  {
+    Desktop.instance.closeAll_actionPerformed(null);
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", DataSourceType.FILE);
+
+    AlignViewport av = af.getViewport();
+    AlignmentI al = av.getAlignment();
+
+    /*
+     * Colour alignment by Buried Index, Above 10% PID, By Conservation 20%
+     */
+    af.changeColour_actionPerformed(JalviewColourScheme.Buried.toString());
+    assertTrue(av.getGlobalColourScheme() instanceof BuriedColourScheme);
+    af.abovePIDThreshold_actionPerformed(true);
+    SliderPanel sp = SliderPanel.getSliderPanel();
+    assertFalse(sp.isForConservation());
+    sp.valueChanged(10);
+    af.conservationMenuItem_actionPerformed(true);
+    sp = SliderPanel.getSliderPanel();
+    assertTrue(sp.isForConservation());
+    sp.valueChanged(20);
+    ResidueShaderI rs = av.getResidueShading();
+    assertEquals(rs.getThreshold(), 10);
+    assertTrue(rs.conservationApplied());
+    assertEquals(rs.getConservationInc(), 20);
+
+    /*
+     * create a group with Strand colouring, 30% Conservation
+     * and 40% PID threshold
+     */
+    SequenceGroup sg = new SequenceGroup();
+    sg.addSequence(al.getSequenceAt(0), false);
+    sg.setStartRes(15);
+    sg.setEndRes(25);
+    av.setSelectionGroup(sg);
+    PopupMenu popupMenu = new PopupMenu(af.alignPanel, null, null);
+    popupMenu.changeColour_actionPerformed(JalviewColourScheme.Strand
+            .toString());
+    assertTrue(sg.getColourScheme() instanceof StrandColourScheme);
+    assertEquals(al.getGroups().size(), 1);
+    assertSame(al.getGroups().get(0), sg);
+    popupMenu.conservationMenuItem_actionPerformed(true);
+    sp = SliderPanel.getSliderPanel();
+    assertTrue(sp.isForConservation());
+    sp.valueChanged(30);
+    popupMenu.abovePIDColour_actionPerformed(true);
+    sp = SliderPanel.getSliderPanel();
+    assertFalse(sp.isForConservation());
+    sp.valueChanged(40);
+    assertTrue(sg.getGroupColourScheme().conservationApplied());
+    assertEquals(sg.getGroupColourScheme().getConservationInc(), 30);
+    assertEquals(sg.getGroupColourScheme().getThreshold(), 40);
+
+    /*
+     * save project, close windows, reload project, verify
+     */
+    File tfile = File.createTempFile("testStoreAndRecoverColourThresholds",
+            ".jvp");
+    tfile.deleteOnExit();
+    new Jalview2XML(false).saveState(tfile);
+    Desktop.instance.closeAll_actionPerformed(null);
+    af = new FileLoader().LoadFileWaitTillLoaded(tfile.getAbsolutePath(),
+            DataSourceType.FILE);
+    Assert.assertNotNull(af, "Failed to reload project");
+
+    /*
+     * verify alignment (background) colouring
+     */
+    rs = af.getViewport().getResidueShading();
+    assertTrue(rs.getColourScheme() instanceof BuriedColourScheme);
+    assertEquals(rs.getThreshold(), 10);
+    assertTrue(rs.conservationApplied());
+    assertEquals(rs.getConservationInc(), 20);
+
+    /*
+     * verify group colouring
+     */
+    assertEquals(1, af.getViewport().getAlignment().getGroups().size(), 1);
+    rs = af.getViewport().getAlignment().getGroups().get(0)
+            .getGroupColourScheme();
+    assertTrue(rs.getColourScheme() instanceof StrandColourScheme);
+    assertEquals(rs.getThreshold(), 40);
+    assertTrue(rs.conservationApplied());
+    assertEquals(rs.getConservationInc(), 30);
+  }
 }
index d867e5e..aa124d9 100644 (file)
@@ -14,7 +14,7 @@ import org.testng.annotations.Test;
 
 public class JalviewFileViewTest
 {
-  @Test
+  @Test(groups = "Functional")
   public void testGetImageIcon()
   {
     JalviewFileView jfv = new JalviewFileView();
@@ -36,7 +36,7 @@ public class JalviewFileViewTest
     assertNull(jfv.getImageIcon("images/file.png"));
   }
 
-  @Test
+  @Test(groups = "Functional")
   public void testGetExtension()
   {
     assertEquals(JalviewFileView.getExtension(new File("text.txt")), "txt");
@@ -48,7 +48,7 @@ public class JalviewFileViewTest
             "/a/longer/file/path/text")));
   }
 
-  @Test
+  @Test(groups = "Functional")
   public void testGetTypeDescription()
   {
     JalviewFileView jfw = new JalviewFileView();
diff --git a/test/jalview/renderer/ResidueShaderTest.java b/test/jalview/renderer/ResidueShaderTest.java
new file mode 100644 (file)
index 0000000..76fd9b4
--- /dev/null
@@ -0,0 +1,166 @@
+package jalview.renderer;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertTrue;
+
+import jalview.analysis.Conservation;
+import jalview.datamodel.Profile;
+import jalview.datamodel.ProfileI;
+import jalview.datamodel.Profiles;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+import jalview.schemes.PIDColourScheme;
+
+import java.awt.Color;
+import java.util.Collections;
+
+import org.testng.annotations.Test;
+
+public class ResidueShaderTest
+{
+
+  @Test(groups = "Functional")
+  public void testAboveThreshold()
+  {
+    /*
+     * make up profiles for this alignment:
+     * AR-Q
+     * AR--
+     * SR-T
+     * SR-T
+     */
+    ProfileI[] profiles = new ProfileI[4];
+    profiles[0] = new Profile(4, 0, 2, "AS");
+    profiles[1] = new Profile(4, 0, 4, "R");
+    profiles[2] = new Profile(4, 4, 0, "");
+    profiles[3] = new Profile(4, 1, 2, "T");
+    ResidueShader ccs = new ResidueShader(new PIDColourScheme());
+    ccs.setConsensus(new Profiles(profiles));
+
+    /*
+     * no threshold
+     */
+    ccs.setThreshold(0, true);
+    assertTrue(ccs.aboveThreshold('a', 0));
+    assertTrue(ccs.aboveThreshold('S', 0));
+    assertTrue(ccs.aboveThreshold('W', 0));
+    assertTrue(ccs.aboveThreshold('R', 1));
+    assertTrue(ccs.aboveThreshold('W', 2));
+    assertTrue(ccs.aboveThreshold('t', 3));
+    assertTrue(ccs.aboveThreshold('Q', 3));
+
+    /*
+     * with threshold, include gaps
+     */
+    ccs.setThreshold(60, false);
+    assertFalse(ccs.aboveThreshold('a', 0));
+    assertFalse(ccs.aboveThreshold('S', 0));
+    assertTrue(ccs.aboveThreshold('R', 1));
+    assertFalse(ccs.aboveThreshold('W', 2));
+    assertFalse(ccs.aboveThreshold('t', 3)); // 50% < 60%
+
+    /*
+     * with threshold, ignore gaps
+     */
+    ccs.setThreshold(60, true);
+    assertFalse(ccs.aboveThreshold('a', 0));
+    assertFalse(ccs.aboveThreshold('S', 0));
+    assertTrue(ccs.aboveThreshold('R', 1));
+    assertFalse(ccs.aboveThreshold('W', 2));
+    assertTrue(ccs.aboveThreshold('t', 3)); // 67% > 60%
+  }
+
+  /**
+   * Test colour bleaching based on conservation score and conservation slider.
+   * Scores of 10 or 11 should leave colours unchanged. Gap is always white.
+   */
+  @Test(groups = "Functional")
+  public void testApplyConservation()
+  {
+    ResidueShader ccs = new ResidueShader(new PIDColourScheme());
+
+    // no conservation present - no fading
+    assertEquals(Color.RED, ccs.applyConservation(Color.RED, 12));
+
+    /*
+     * stub Conservation to return a given consensus string
+     */
+    final String consSequence = "0123456789+*-";
+    Conservation cons = new Conservation(null,
+            Collections.<SequenceI> emptyList(), 0, 0)
+    {
+      @Override
+      public SequenceI getConsSequence()
+      {
+        return new Sequence("seq", consSequence);
+      }
+    };
+    ccs.setConservation(cons);
+
+    // column out of range:
+    assertEquals(Color.RED,
+            ccs.applyConservation(Color.RED, consSequence.length()));
+
+    /*
+     * with 100% threshold, 'fade factor' is 
+     * (11-score)/10 * 100/20 = (11-score)/2
+     * which is >= 1 for all scores i.e. all fade to white except +, *
+     */
+    ccs.setConservationInc(100);
+    assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 0));
+    assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 1));
+    assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 2));
+    assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 3));
+    assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 4));
+    assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 5));
+    assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 6));
+    assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 7));
+    assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 8));
+    assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 9));
+    assertEquals(Color.RED, ccs.applyConservation(Color.RED, 10));
+    assertEquals(Color.RED, ccs.applyConservation(Color.RED, 11));
+    assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 12));
+
+    /*
+     * with 0% threshold, there should be no fading
+     */
+    ccs.setConservationInc(0);
+    assertEquals(Color.RED, ccs.applyConservation(Color.RED, 0));
+    assertEquals(Color.RED, ccs.applyConservation(Color.RED, 1));
+    assertEquals(Color.RED, ccs.applyConservation(Color.RED, 2));
+    assertEquals(Color.RED, ccs.applyConservation(Color.RED, 3));
+    assertEquals(Color.RED, ccs.applyConservation(Color.RED, 4));
+    assertEquals(Color.RED, ccs.applyConservation(Color.RED, 5));
+    assertEquals(Color.RED, ccs.applyConservation(Color.RED, 6));
+    assertEquals(Color.RED, ccs.applyConservation(Color.RED, 7));
+    assertEquals(Color.RED, ccs.applyConservation(Color.RED, 8));
+    assertEquals(Color.RED, ccs.applyConservation(Color.RED, 9));
+    assertEquals(Color.RED, ccs.applyConservation(Color.RED, 10));
+    assertEquals(Color.RED, ccs.applyConservation(Color.RED, 11));
+    assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 12)); // gap
+
+    /*
+     * with 40% threshold, 'fade factor' is 
+     * (11-score)/10 * 40/20 = (11-score)/5
+     * which is {>1, >1, >1, >1, >1, >1, 1, 0.8, 0.6, 0.4} for score 0-9
+     * e.g. score 7 colour fades 80% of the way to white (255, 255, 255)
+     */
+    ccs.setConservationInc(40);
+    Color colour = new Color(155, 105, 55);
+    assertEquals(Color.WHITE, ccs.applyConservation(colour, 0));
+    assertEquals(Color.WHITE, ccs.applyConservation(colour, 1));
+    assertEquals(Color.WHITE, ccs.applyConservation(colour, 2));
+    assertEquals(Color.WHITE, ccs.applyConservation(colour, 3));
+    assertEquals(Color.WHITE, ccs.applyConservation(colour, 4));
+    assertEquals(Color.WHITE, ccs.applyConservation(colour, 5));
+    assertEquals(Color.WHITE, ccs.applyConservation(colour, 6));
+    assertEquals(new Color(235, 225, 215), ccs.applyConservation(colour, 7));
+    assertEquals(new Color(215, 195, 175), ccs.applyConservation(colour, 8));
+    assertEquals(new Color(195, 165, 135), ccs.applyConservation(colour, 9));
+    assertEquals(colour, ccs.applyConservation(colour, 10));
+    assertEquals(colour, ccs.applyConservation(colour, 11));
+    assertEquals(Color.WHITE, ccs.applyConservation(colour, 12));
+  }
+
+}
diff --git a/test/jalview/renderer/ScaleRendererTest.java b/test/jalview/renderer/ScaleRendererTest.java
new file mode 100644 (file)
index 0000000..cf1039f
--- /dev/null
@@ -0,0 +1,73 @@
+package jalview.renderer;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import jalview.gui.AlignFrame;
+import jalview.gui.AlignViewport;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+import jalview.renderer.ScaleRenderer.ScaleMark;
+
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+public class ScaleRendererTest
+{
+  @Test(groups = "Functional")
+  public void testCalculateMarks()
+  {
+    String data = ">Seq/20-45\nABCDEFGHIJKLMNOPQRSTUVWXYS\n";
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(data,
+            DataSourceType.PASTE);
+    AlignViewport av = af.getViewport();
+
+    /*
+     * scale has minor ticks at 5 and 15, major at 10 and 20
+     * (these are base 1, ScaleMark holds base 0 values)
+     */
+    List<ScaleMark> marks = new ScaleRenderer().calculateMarks(av, 0, 25);
+    assertEquals(marks.size(), 4);
+
+    assertFalse(marks.get(0).major);
+    assertEquals(marks.get(0).column, 4);
+    assertNull(marks.get(0).text);
+
+    assertTrue(marks.get(1).major);
+    assertEquals(marks.get(1).column, 9);
+    assertEquals(marks.get(1).text, "10");
+
+    assertFalse(marks.get(2).major);
+    assertEquals(marks.get(2).column, 14);
+    assertNull(marks.get(2).text);
+
+    assertTrue(marks.get(3).major);
+    assertEquals(marks.get(3).column, 19);
+    assertEquals(marks.get(3).text, "20");
+
+    /*
+     * now hide columns 9-11 and 18-20 (base 1)
+     * scale marks are now in the same columns as before, but
+     * with column numbering adjusted for hidden columns
+     */
+    av.hideColumns(8, 10);
+    av.hideColumns(17, 19);
+    marks = new ScaleRenderer().calculateMarks(av, 0, 25);
+    assertEquals(marks.size(), 4);
+    assertFalse(marks.get(0).major);
+    assertEquals(marks.get(0).column, 4);
+    assertNull(marks.get(0).text);
+    assertTrue(marks.get(1).major);
+    assertEquals(marks.get(1).column, 9);
+    assertEquals(marks.get(1).text, "13"); // +3 hidden columns
+    assertFalse(marks.get(2).major);
+    assertEquals(marks.get(2).column, 14);
+    assertNull(marks.get(2).text);
+    assertTrue(marks.get(3).major);
+    assertEquals(marks.get(3).column, 19);
+    assertEquals(marks.get(3).text, "26"); // +6 hidden columns
+  }
+}
diff --git a/test/jalview/schemes/Blosum62ColourSchemeTest.java b/test/jalview/schemes/Blosum62ColourSchemeTest.java
new file mode 100644 (file)
index 0000000..b3dd165
--- /dev/null
@@ -0,0 +1,57 @@
+package jalview.schemes;
+
+import static org.testng.Assert.assertEquals;
+
+import java.awt.Color;
+
+import org.testng.annotations.Test;
+
+public class Blosum62ColourSchemeTest
+{
+  /**
+   * Test the method that determines colour as:
+   * <ul>
+   * <li>white if there is no consensus</li>
+   * <li>white if 'residue' is a gap</li>
+   * <li>dark blue if residue matches consensus (or joint consensus)</li>
+   * <li>else, total the residue's Blosum score with the consensus residue(s)</li>
+   * <ul>
+   * <li>if positive, light blue, else white</li>
+   * </ul>
+   * <ul>
+   */
+  @Test
+  public void testFindColour()
+  {
+    ColourSchemeI blosum = new Blosum62ColourScheme();
+    Color lightBlue = new Color(204, 204, 255);
+    Color darkBlue = new Color(154, 154, 255);
+
+    /*
+     * findColour does not use column, sequence or pid score
+     */
+    assertEquals(blosum.findColour('A', 0, null, "A", 0f), darkBlue);
+    assertEquals(blosum.findColour('a', 0, null, "A", 0f), darkBlue);
+    assertEquals(blosum.findColour('A', 0, null, "a", 0f), darkBlue);
+    assertEquals(blosum.findColour('a', 0, null, "a", 0f), darkBlue);
+
+    /*
+     * L has a Blosum score of 
+     * -1 with A
+     * -4 with B
+     * 0 with F
+     * 2 with I
+     * -1 with T
+     * 1 with V
+     * etc
+     */
+    assertEquals(blosum.findColour('L', 0, null, "A", 0f), Color.white); // -1
+    assertEquals(blosum.findColour('L', 0, null, "B", 0f), Color.white); // -4
+    assertEquals(blosum.findColour('L', 0, null, "F", 0f), Color.white); // 0
+    assertEquals(blosum.findColour('L', 0, null, "I", 0f), lightBlue); // 2
+    assertEquals(blosum.findColour('L', 0, null, "TV", 0f), Color.white); // 0
+    assertEquals(blosum.findColour('L', 0, null, "IV", 0f), lightBlue); // 3
+    assertEquals(blosum.findColour('L', 0, null, "IT", 0f), lightBlue); // 1
+    assertEquals(blosum.findColour('L', 0, null, "IAT", 0f), Color.white); // 0
+  }
+}
diff --git a/test/jalview/schemes/ClustalxColourSchemeTest.java b/test/jalview/schemes/ClustalxColourSchemeTest.java
new file mode 100644 (file)
index 0000000..d35ca76
--- /dev/null
@@ -0,0 +1,134 @@
+package jalview.schemes;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.datamodel.AlignmentI;
+import jalview.gui.AlignFrame;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+
+import java.awt.Color;
+
+import org.testng.annotations.Test;
+
+public class ClustalxColourSchemeTest
+{
+  // @formatter:off
+  private static final String FASTA = 
+          ">seq1\nAAANNNRQ\n" + 
+          ">seq2\nAAANNNRQ\n" + 
+          ">seq3\nAAANNNRQ\n" + 
+          ">seq4\nAAANNNRQ\n" + 
+          ">seq5\nAAANYYKQ\n" + 
+          ">seq6\nAAANYYKQ\n" + 
+          ">seq7\nAVKWYYKQ\n" + 
+          ">seq8\nKKKWYYQQ\n" + 
+          ">seq9\nKKKWWYQQ\n" + 
+          ">seq0\nKKKWWWQW\n";
+  // @formatter:on
+
+  @Test(groups = "Functional")
+  public void testFindColour()
+  {
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(FASTA,
+            DataSourceType.PASTE);
+    AlignmentI al = af.getViewport().getAlignment();
+    ClustalxColourScheme cs = new ClustalxColourScheme(al, null);
+
+    /*
+     * column 1 is 70% A which is above Clustalx threshold of 60%
+     */
+    Color clustalBlue = new Color(0.5f, 0.7f, 0.9f);
+    assertEquals(cs.findColour('A', 0, al.getSequenceAt(0)), clustalBlue);
+
+    /*
+     * column 2 is 70% A or V which is above Clustalx threshold for group
+     */
+    assertEquals(cs.findColour('A', 0, al.getSequenceAt(1)), clustalBlue);
+
+    /*
+     * column 3 is 60% A which is not above Clustalx threshold
+     * the Ks in the other rows are not in the same Clustalx group
+     */
+    assertEquals(cs.findColour('A', 2, al.getSequenceAt(1)), Color.white);
+
+    /*
+     * column 4 is 60% N which is above Clustalx threshold of 50%
+     */
+    Color clustalGreen = new Color(0.1f, 0.8f, 0.1f);
+    assertEquals(cs.findColour('N', 3, al.getSequenceAt(1)), clustalGreen);
+
+    /*
+     * column 5 is 40% N and 40% Y which fails to pass the threshold of
+     * 50% N or 85% either
+     */
+    assertEquals(cs.findColour('N', 4, al.getSequenceAt(1)), Color.white);
+
+    /*
+     * column 6 is 40% N and 50% Y which fails to pass the threshold of
+     * 85% for either
+     */
+    assertEquals(cs.findColour('N', 5, al.getSequenceAt(1)), Color.white);
+
+    /*
+     * column 7 is 40% R and 30% K which combine to make > 60%
+     */
+    Color clustalRed = new Color(0.9f, 0.2f, 0.1f);
+    assertEquals(cs.findColour('R', 6, al.getSequenceAt(1)), clustalRed);
+    assertEquals(cs.findColour('K', 6, al.getSequenceAt(7)), clustalRed);
+
+    /*
+     * column 8 is >85% Q which qualifies K and R to be red
+     */
+    assertEquals(cs.findColour('R', 7, al.getSequenceAt(1)), clustalRed);
+    assertEquals(cs.findColour('K', 7, al.getSequenceAt(1)), clustalRed);
+
+    // TODO more test cases; check if help documentation matches implementation
+  }
+
+  // @formatter:on
+  
+  /**
+   * Test for colour calculation when the consensus percentage ignores gapped
+   * sequences
+   */
+  @Test(groups = "Functional")
+  public void testFindColour_ignoreGaps()
+  {
+    /*
+     * CCC
+     * CCC
+     * -CC
+     * first column is 66% C (blue) including gaps
+     * or 100% C ignoring gaps
+     */
+    String fasta = ">seq1\nCCC\n>seq2\nccc\n>seq3\n-CC\n";
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(fasta,
+            DataSourceType.PASTE);
+    AlignmentI al = af.getViewport().getAlignment();
+    ClustalxColourScheme cs = new ClustalxColourScheme(al, null);
+  
+    /*
+     * column 1 is 66% C which is above Clustalx threshold of 60%
+     */
+    Color clustalBlue = ClustalxColourScheme.ClustalColour.BLUE.colour;
+    assertEquals(cs.findColour('C', 0, al.getSequenceAt(0)), clustalBlue);
+
+    /*
+     * set directly to ignore gaps
+     */
+    cs.setIncludeGaps(false);
+    Color clustalPink = ClustalxColourScheme.ClustalColour.PINK.colour;
+    assertEquals(cs.findColour('C', 0, al.getSequenceAt(0)), clustalPink);
+
+    /*
+     * set ignore gaps on the viewport...
+     */
+    cs.setIncludeGaps(true);
+    assertEquals(cs.findColour('C', 0, al.getSequenceAt(0)), clustalBlue);
+    af.getViewport().setIgnoreGapsConsensus(true, af.alignPanel);
+    // next test fails: colour scheme does not read ignore gaps flag from
+    // viewport
+    // assertEquals(cs.findColour('C', 0, al.getSequenceAt(0)), clustalPink);
+  }
+}
diff --git a/test/jalview/schemes/ColourSchemePropertyTest.java b/test/jalview/schemes/ColourSchemePropertyTest.java
new file mode 100644 (file)
index 0000000..11562b8
--- /dev/null
@@ -0,0 +1,135 @@
+package jalview.schemes;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+
+import java.awt.Color;
+
+import org.testng.annotations.Test;
+
+public class ColourSchemePropertyTest
+{
+  @Test(groups = "Functional")
+  public void testGetColourName()
+  {
+    SequenceI seq = new Sequence("Seq1", "abcd");
+    AlignmentI al = new Alignment(new SequenceI[] { seq });
+    ColourSchemeI cs = new ClustalxColourScheme(al, null);
+    assertEquals(ColourSchemeProperty.getColourName(cs), "Clustal");
+    cs = new Blosum62ColourScheme();
+    assertEquals(ColourSchemeProperty.getColourName(cs), "Blosum62");
+    cs = new PIDColourScheme();
+    assertEquals(ColourSchemeProperty.getColourName(cs), "% Identity");
+    cs = new HydrophobicColourScheme();
+    assertEquals(ColourSchemeProperty.getColourName(cs), "Hydrophobic");
+    cs = new ZappoColourScheme();
+    assertEquals(ColourSchemeProperty.getColourName(cs), "Zappo");
+    cs = new TaylorColourScheme();
+    assertEquals(ColourSchemeProperty.getColourName(cs), "Taylor");
+    cs = new HelixColourScheme();
+    assertEquals(ColourSchemeProperty.getColourName(cs),
+            "Helix Propensity");
+    cs = new StrandColourScheme();
+    assertEquals(ColourSchemeProperty.getColourName(cs),
+            "Strand Propensity");
+    cs = new TurnColourScheme();
+    assertEquals(ColourSchemeProperty.getColourName(cs), "Turn Propensity");
+    cs = new BuriedColourScheme();
+    assertEquals(ColourSchemeProperty.getColourName(cs), "Buried Index");
+    cs = new NucleotideColourScheme();
+    assertEquals(ColourSchemeProperty.getColourName(cs), "Nucleotide");
+    cs = new PurinePyrimidineColourScheme();
+    assertEquals(ColourSchemeProperty.getColourName(cs),
+            "Purine/Pyrimidine");
+    cs = new TCoffeeColourScheme(al);
+    assertEquals(ColourSchemeProperty.getColourName(cs), "T-Coffee Scores");
+    cs = new RNAHelicesColour(al);
+    assertEquals(ColourSchemeProperty.getColourName(cs), "RNA Helices");
+    cs = new RNAInteractionColourScheme();
+    assertEquals(ColourSchemeProperty.getColourName(cs),
+            "RNA Interaction type");
+    cs = new UserColourScheme();
+    assertEquals(ColourSchemeProperty.getColourName(cs), "User Defined");
+
+    /*
+     * UserColourScheme may have a bespoke name
+     */
+    ((UserColourScheme) cs).setName("stripy");
+    assertEquals(ColourSchemeProperty.getColourName(cs), "stripy");
+    ((UserColourScheme) cs).setName("");
+    assertEquals(ColourSchemeProperty.getColourName(cs), "User Defined");
+    ((UserColourScheme) cs).setName(null);
+    assertEquals(ColourSchemeProperty.getColourName(cs), "User Defined");
+
+    assertEquals(ColourSchemeProperty.getColourName(null), "None");
+  }
+
+  @Test(groups = "Functional")
+  public void testGetColourScheme()
+  {
+    SequenceI seq = new Sequence("Seq1", "abcd");
+    AlignmentI al = new Alignment(new SequenceI[] { seq });
+    // the strings here correspond to JalviewColourScheme.toString() values
+    ColourSchemeI cs = ColourSchemeProperty.getColourScheme(al, "Clustal");
+    assertTrue(cs instanceof ClustalxColourScheme);
+    // not case-sensitive
+    cs = ColourSchemeProperty.getColourScheme(al, "CLUSTAL");
+    assertTrue(cs instanceof ClustalxColourScheme);
+    cs = ColourSchemeProperty.getColourScheme(al, "clustal");
+    assertTrue(cs instanceof ClustalxColourScheme);
+    cs = ColourSchemeProperty.getColourScheme(al, "Blosum62");
+    assertTrue(cs instanceof Blosum62ColourScheme);
+    cs = ColourSchemeProperty.getColourScheme(al, "% Identity");
+    assertTrue(cs instanceof PIDColourScheme);
+    cs = ColourSchemeProperty.getColourScheme(al, "Zappo");
+    assertTrue(cs instanceof ZappoColourScheme);
+    cs = ColourSchemeProperty.getColourScheme(al, "Taylor");
+    assertTrue(cs instanceof TaylorColourScheme);
+    cs = ColourSchemeProperty.getColourScheme(al, "Hydrophobic");
+    assertTrue(cs instanceof HydrophobicColourScheme);
+    cs = ColourSchemeProperty.getColourScheme(al, "Helix Propensity");
+    assertTrue(cs instanceof HelixColourScheme);
+    cs = ColourSchemeProperty.getColourScheme(al, "Strand Propensity");
+    assertTrue(cs instanceof StrandColourScheme);
+    cs = ColourSchemeProperty.getColourScheme(al, "Turn Propensity");
+    assertTrue(cs instanceof TurnColourScheme);
+    cs = ColourSchemeProperty.getColourScheme(al, "Buried Index");
+    assertTrue(cs instanceof BuriedColourScheme);
+    cs = ColourSchemeProperty.getColourScheme(al, "Nucleotide");
+    assertTrue(cs instanceof NucleotideColourScheme);
+    cs = ColourSchemeProperty.getColourScheme(al, "Purine/Pyrimidine");
+    assertTrue(cs instanceof PurinePyrimidineColourScheme);
+    cs = ColourSchemeProperty.getColourScheme(al, "T-Coffee Scores");
+    assertTrue(cs instanceof TCoffeeColourScheme);
+    cs = ColourSchemeProperty.getColourScheme(al, "RNA Helices");
+    assertTrue(cs instanceof RNAHelicesColour);
+    // 'None' is a special value
+    assertNull(ColourSchemeProperty.getColourScheme(al, "None"));
+    assertNull(ColourSchemeProperty.getColourScheme(al, "none"));
+    // default is to convert the name into a fixed colour
+    cs = ColourSchemeProperty.getColourScheme(al, "elephants");
+    assertTrue(cs instanceof UserColourScheme);
+
+    /*
+     * explicit aa colours
+     */
+    UserColourScheme ucs = (UserColourScheme) ColourSchemeProperty
+            .getColourScheme(al,
+            "R,G=red;C=blue;c=green;Q=10,20,30;S,T=11ffdd");
+    assertEquals(ucs.findColour('H'), Color.white);
+    assertEquals(ucs.findColour('R'), Color.red);
+    assertEquals(ucs.findColour('r'), Color.red);
+    assertEquals(ucs.findColour('G'), Color.red);
+    assertEquals(ucs.findColour('C'), Color.blue);
+    assertEquals(ucs.findColour('c'), Color.green);
+    assertEquals(ucs.findColour('Q'), new Color(10, 20, 30));
+    assertEquals(ucs.findColour('S'), new Color(0x11ffdd));
+    assertEquals(ucs.findColour('T'), new Color(0x11ffdd));
+  }
+}
diff --git a/test/jalview/schemes/ColourSchemesTest.java b/test/jalview/schemes/ColourSchemesTest.java
new file mode 100644 (file)
index 0000000..4618ed7
--- /dev/null
@@ -0,0 +1,299 @@
+package jalview.schemes;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import jalview.bin.Cache;
+import jalview.bin.Jalview;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.Desktop;
+import jalview.gui.SequenceRenderer;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+import jalview.schemes.ClustalxColourScheme.ClustalColour;
+
+import java.awt.Color;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class ColourSchemesTest
+{
+  /*
+   * a colour scheme that alternates Taylor and Zappo
+   * colouring by column
+   */
+  class Stripy extends ResidueColourScheme
+  {
+    private ResidueColourScheme odd;
+
+    private ResidueColourScheme even;
+
+    private Stripy()
+    {
+    }
+
+    /**
+     * constructor given colours for odd and even columns
+     * 
+     * @param odd
+     * @param even
+     */
+    private Stripy(ColourSchemeI cs1, ColourSchemeI cs2)
+    {
+      odd = (ResidueColourScheme) cs1;
+      even = (ResidueColourScheme) cs2;
+    }
+
+    @Override
+    public ColourSchemeI getInstance(AnnotatedCollectionI sg,
+            Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
+    {
+      final ColourSchemeI cs1 = ColourSchemes.getInstance()
+              .getColourScheme(JalviewColourScheme.Taylor.toString(),
+                      (AnnotatedCollectionI) null);
+      final ColourSchemeI cs2 = ColourSchemes.getInstance()
+              .getColourScheme(JalviewColourScheme.Zappo.toString(),
+                      (AnnotatedCollectionI) null);
+      return new Stripy(cs1, cs2);
+    }
+
+    @Override
+    public Color findColour(char c, int j, SequenceI seq)
+    {
+      if (j % 2 == 1)
+      {
+        return odd.findColour(c, j, seq);
+      }
+      else
+      {
+        return even.findColour(c, j, seq);
+      }
+    }
+
+    @Override
+    public String getSchemeName()
+    {
+      return "stripy";
+    }
+  };
+  
+  /*
+   * a colour scheme that is Clustal but using AWT colour equivalents
+   */
+  class MyClustal extends ResidueColourScheme
+  {
+    ClustalxColourScheme delegate;
+
+    private MyClustal()
+    {
+    }
+
+    private MyClustal(AnnotatedCollectionI sg,
+            Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
+    {
+      delegate = new ClustalxColourScheme(sg, hiddenRepSequences);
+    }
+
+    @Override
+    public Color findColour(char c, int j, SequenceI seq)
+    {
+      Color col = delegate.findColour(c, j, seq);
+      Color result = col;
+      if (col.equals(ClustalColour.BLUE.colour))
+      {
+        result = Color.blue;
+      }
+      else if (col.equals(ClustalColour.CYAN.colour))
+      {
+        result = Color.cyan;
+      }
+      else if (col.equals(ClustalColour.GREEN.colour))
+      {
+        result = Color.green;
+      }
+      else if (col.equals(ClustalColour.MAGENTA.colour))
+      {
+        result = Color.magenta;
+      }
+      else if (col.equals(ClustalColour.ORANGE.colour))
+      {
+        result = Color.orange;
+      }
+      else if (col.equals(ClustalColour.PINK.colour))
+      {
+        result = Color.pink;
+      }
+      else if (col.equals(ClustalColour.RED.colour))
+      {
+        result = Color.red;
+      }
+      else if (col.equals(ClustalColour.YELLOW.colour))
+      {
+        result = Color.yellow;
+      }
+      return result;
+    }
+
+    @Override
+    public ColourSchemeI getInstance(AnnotatedCollectionI sg,
+            Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
+    {
+      return new MyClustal(sg,              hiddenRepSequences);
+    }
+
+    @Override
+    public String getSchemeName()
+    {
+      return "MyClustal";
+    }
+
+  }
+
+  @BeforeClass(alwaysRun = true)
+  public static void setUpBeforeClass() throws Exception
+  {
+    /*
+     * use read-only test properties file
+     */
+    Cache.loadProperties("test/jalview/io/testProps.jvprops");
+    Jalview.main(new String[] { "-nonews" });
+  }
+
+  @AfterClass(alwaysRun = true)
+  public static void tearDownAfterClass() throws Exception
+  {
+    Desktop.instance.closeAll_actionPerformed(null);
+  }
+
+  @Test(groups = "Functional")
+  public void testGetColourSchemes()
+  {
+    /*
+     * this just verifies that built-in colour schemes are loaded into ColourSchemes
+     * in the order in which they are declared in the JalviewColourScheme enum
+     * (this also determines their order in Colour menus)
+     */
+    Iterator<ColourSchemeI> schemes = ColourSchemes.getInstance().getColourSchemes().iterator();
+    JalviewColourScheme[] jalviewSchemes = JalviewColourScheme.values();
+    int i = 0;
+    while (schemes.hasNext() && i < jalviewSchemes.length)
+    {
+      assertTrue(schemes.next().getSchemeName()
+              .equals(jalviewSchemes[i].toString()));
+      i++;
+    }
+  }
+
+  @Test(groups = "Functional")
+  public void testGetColourScheme()
+  {
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            ">seq1\nAGLRTWQU", DataSourceType.PASTE);
+    ColourSchemes schemes = ColourSchemes.getInstance();
+
+    AnnotatedCollectionI al = af.getViewport().getAlignment();
+
+    for (JalviewColourScheme cs : JalviewColourScheme.values())
+    {
+      ColourSchemeI registered = schemes.getColourScheme(cs.toString(), al);
+      assertSame(registered.getClass(), cs.getSchemeClass());
+    }
+    af.closeMenuItem_actionPerformed(true);
+  }
+  
+  @Test(groups = "Functional")
+  public void testRegisterColourScheme()
+  {
+    ColourSchemes.getInstance().registerColourScheme(new Stripy());
+    ColourSchemes.getInstance().registerColourScheme(new MyClustal());
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", DataSourceType.FILE);
+    /*
+     * set a breakpoint here to see and play with the newly registered
+     *  colour schemes in the AlignFrame colour menu
+     */
+    SequenceRenderer sr = new SequenceRenderer(af.getViewport());
+    SequenceI seq = af.getViewport().getAlignment().findName("FER_CAPAA");
+
+    /*
+     * set and check Taylor colours
+     */
+    af.changeColour_actionPerformed(JalviewColourScheme.Taylor.toString());
+    Color taylor1 = sr.getResidueBoxColour(seq, 88); // E 255,0,102
+    Color taylor2 = sr.getResidueBoxColour(seq, 89); // A 204,255,0
+    Color taylor3 = sr.getResidueBoxColour(seq, 90); // G 255,153,0
+    assertEquals(taylor1, new Color(255, 0, 102));
+    assertEquals(taylor2, new Color(204, 255, 0));
+    assertEquals(taylor3, new Color(255, 153, 0));
+
+    /*
+     * set and check Zappo colours
+     */
+    af.changeColour_actionPerformed(JalviewColourScheme.Zappo.toString());
+    Color zappo1 = sr.getResidueBoxColour(seq, 88); // E red
+    Color zappo2 = sr.getResidueBoxColour(seq, 89); // A pink
+    Color zappo3 = sr.getResidueBoxColour(seq, 90); // G magenta
+    assertEquals(zappo1, Color.red);
+    assertEquals(zappo2, Color.pink);
+    assertEquals(zappo3, Color.magenta);
+
+    /*
+     * set 'stripy' colours - odd columns are Taylor and even are Zappo 
+     */
+    af.changeColour_actionPerformed("stripy");
+    Color stripy1 = sr.getResidueBoxColour(seq, 88);
+    Color stripy2 = sr.getResidueBoxColour(seq, 89);
+    Color stripy3 = sr.getResidueBoxColour(seq, 90);
+    assertEquals(stripy1, zappo1);
+    assertEquals(stripy2, taylor2);
+    assertEquals(stripy3, zappo3);
+
+    /*
+     * set and check Clustal colours
+     */
+    af.changeColour_actionPerformed(JalviewColourScheme.Clustal.toString());
+    Color clustal1 = sr.getResidueBoxColour(seq, 88);
+    Color clustal2 = sr.getResidueBoxColour(seq, 89);
+    Color clustal3 = sr.getResidueBoxColour(seq, 90);
+    assertEquals(clustal1, ClustalColour.MAGENTA.colour);
+    assertEquals(clustal2, ClustalColour.BLUE.colour);
+    assertEquals(clustal3, ClustalColour.ORANGE.colour);
+
+    /*
+     * set 'MyClustal' colours - uses AWT colour equivalents
+     */
+    af.changeColour_actionPerformed("MyClustal");
+    Color myclustal1 = sr.getResidueBoxColour(seq, 88);
+    Color myclustal2 = sr.getResidueBoxColour(seq, 89);
+    Color myclustal3 = sr.getResidueBoxColour(seq, 90);
+    assertEquals(myclustal1, Color.MAGENTA);
+    assertEquals(myclustal2, Color.BLUE);
+    assertEquals(myclustal3, Color.ORANGE);
+  }
+
+  /**
+   * Tests for check if scheme name exists. Built-in scheme names are the
+   * toString() values of enum JalviewColourScheme.
+   */
+  @Test(groups = "Functional")
+  public void testNameExists()
+  {
+    ColourSchemes cs = ColourSchemes.getInstance();
+    assertFalse(cs.nameExists(null));
+    assertFalse(cs.nameExists(""));
+    assertTrue(cs.nameExists("Clustal"));
+    assertTrue(cs.nameExists("CLUSTAL"));
+    assertFalse(cs.nameExists("CLUSTAL "));
+    assertTrue(cs.nameExists("% Identity"));
+    assertFalse(cs.nameExists("PID"));
+  }
+}
index 47613a1..c16d541 100644 (file)
@@ -27,6 +27,7 @@ import static org.testng.AssertJUnit.fail;
 
 import jalview.datamodel.SequenceFeature;
 import jalview.gui.JvOptionPane;
+import jalview.util.ColorUtils;
 import jalview.util.Format;
 
 import java.awt.Color;
@@ -146,7 +147,7 @@ public class FeatureColourTest
     fc.setColourByLabel(true);
     SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 1f,
             null);
-    Color expected = UserColourScheme.createColourFromName("desc");
+    Color expected = ColorUtils.createColourFromName("desc");
     assertEquals(expected, fc.getColor(sf));
   }
 
diff --git a/test/jalview/schemes/JalviewColourSchemeTest.java b/test/jalview/schemes/JalviewColourSchemeTest.java
new file mode 100644 (file)
index 0000000..d9403d2
--- /dev/null
@@ -0,0 +1,48 @@
+package jalview.schemes;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.testng.annotations.Test;
+
+public class JalviewColourSchemeTest
+{
+  @Test(groups = "Functional")
+  public void testGetSchemeClass()
+  {
+    assertTrue(JalviewColourScheme.Clustal.getSchemeClass() == ClustalxColourScheme.class);
+    assertTrue(JalviewColourScheme.Blosum62.getSchemeClass() == Blosum62ColourScheme.class);
+    assertTrue(JalviewColourScheme.PID.getSchemeClass() == PIDColourScheme.class);
+    assertTrue(JalviewColourScheme.Hydrophobic.getSchemeClass() == HydrophobicColourScheme.class);
+    assertTrue(JalviewColourScheme.Zappo.getSchemeClass() == ZappoColourScheme.class);
+    assertTrue(JalviewColourScheme.Taylor.getSchemeClass() == TaylorColourScheme.class);
+    assertTrue(JalviewColourScheme.Helix.getSchemeClass() == HelixColourScheme.class);
+    assertTrue(JalviewColourScheme.Strand.getSchemeClass() == StrandColourScheme.class);
+    assertTrue(JalviewColourScheme.Turn.getSchemeClass() == TurnColourScheme.class);
+    assertTrue(JalviewColourScheme.Buried.getSchemeClass() == BuriedColourScheme.class);
+    assertTrue(JalviewColourScheme.Nucleotide.getSchemeClass() == NucleotideColourScheme.class);
+    assertTrue(JalviewColourScheme.PurinePyrimidine.getSchemeClass() == PurinePyrimidineColourScheme.class);
+    assertTrue(JalviewColourScheme.TCoffee.getSchemeClass() == TCoffeeColourScheme.class);
+    assertTrue(JalviewColourScheme.RNAHelices.getSchemeClass() == RNAHelicesColour.class);
+  }
+
+  @Test(groups = "Functional")
+  public void testToString()
+  {
+    assertEquals(JalviewColourScheme.Clustal.toString(), "Clustal");
+    assertEquals(JalviewColourScheme.Blosum62.toString(), "Blosum62");
+    assertEquals(JalviewColourScheme.PID.toString(), "% Identity");
+    assertEquals(JalviewColourScheme.Zappo.toString(), "Zappo");
+    assertEquals(JalviewColourScheme.Taylor.toString(), "Taylor");
+    assertEquals(JalviewColourScheme.Hydrophobic.toString(), "Hydrophobic");
+    assertEquals(JalviewColourScheme.Helix.toString(), "Helix Propensity");
+    assertEquals(JalviewColourScheme.Strand.toString(), "Strand Propensity");
+    assertEquals(JalviewColourScheme.Turn.toString(), "Turn Propensity");
+    assertEquals(JalviewColourScheme.Buried.toString(), "Buried Index");
+    assertEquals(JalviewColourScheme.Nucleotide.toString(), "Nucleotide");
+    assertEquals(JalviewColourScheme.PurinePyrimidine.toString(),
+            "Purine/Pyrimidine");
+    assertEquals(JalviewColourScheme.TCoffee.toString(), "T-Coffee Scores");
+    assertEquals(JalviewColourScheme.RNAHelices.toString(), "RNA Helices");
+  }
+}
diff --git a/test/jalview/schemes/PIDColourSchemeTest.java b/test/jalview/schemes/PIDColourSchemeTest.java
new file mode 100644 (file)
index 0000000..73b270f
--- /dev/null
@@ -0,0 +1,104 @@
+package jalview.schemes;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.AlignViewport;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+
+import java.awt.Color;
+
+import org.testng.annotations.Test;
+
+public class PIDColourSchemeTest
+{
+  static final Color white = Color.white;
+
+  static final Color over40 = new Color(204, 204, 255);
+
+  static final Color over60 = new Color(153, 153, 255);
+
+  static final Color over80 = new Color(100, 100, 255);
+
+  /**
+   * Test findColour for cases:
+   * <ul>
+   * <li>gap: white</li>
+   * <li>no match to consensus: white</li>
+   * <li>match consensus with pid > 80%: 100,100,255</li>
+   * <li>match consensus with pid > 60%: 153, 153, 255</li>
+   * <li>match consensus with pid > 40%: 204, 204, 255</li>
+   * <li>match consensus with pid <= 40%: white</li>
+   * <li>joint consensus matching</li>
+   * <li>case insensitive matching</li>
+   * <ul>
+   */
+  @Test(groups = "Functional")
+  public void testFindColour()
+  {
+    ColourSchemeI scheme = new PIDColourScheme();
+
+    /*
+     * doesn't use column or sequence
+     */
+    assertEquals(scheme.findColour('A', 0, null, "A", 0f), white);
+    assertEquals(scheme.findColour('A', 0, null, "A", 40f), white);
+    assertEquals(scheme.findColour('A', 0, null, "A", 40.1f), over40);
+    assertEquals(scheme.findColour('A', 0, null, "A", 60f), over40);
+    assertEquals(scheme.findColour('A', 0, null, "A", 60.1f), over60);
+    assertEquals(scheme.findColour('A', 0, null, "A", 80f), over60);
+    assertEquals(scheme.findColour('A', 0, null, "A", 80.1f), over80);
+    assertEquals(scheme.findColour('A', 0, null, "A", 100f), over80);
+    assertEquals(scheme.findColour('A', 0, null, "KFV", 100f), white);
+
+    assertEquals(scheme.findColour('a', 0, null, "A", 80f), over60);
+    assertEquals(scheme.findColour('A', 0, null, "a", 80f), over60);
+    assertEquals(scheme.findColour('a', 0, null, "a", 80f), over60);
+    assertEquals(scheme.findColour('A', 0, null, "AC", 80f), over60);
+    assertEquals(scheme.findColour('A', 0, null, "KCA", 80f), over60);
+  }
+
+  /**
+   * Test that changing the 'ignore gaps in consensus' in the viewport (an
+   * option on the annotation label popup menu) results in a change to the
+   * colouring
+   */
+  @Test(groups = "Functional")
+  public void testFindColour_ignoreGaps()
+  {
+    /*
+     * AAAAA
+     * AAAAA
+     * -CCCC
+     * FFFFF
+     * 
+     * first column consensus is A
+     * first column PID is 50%, or 67% ignoring gaps
+     */
+    String seqs = ">seq1\nAAAAA\n>seq2\nAAAAA\n>seq3\n-CCCC\n>seq4\nFFFFF\n";
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(seqs,
+            DataSourceType.PASTE);
+    AlignViewport viewport = af.getViewport();
+    viewport.setIgnoreGapsConsensus(false, af.alignPanel);
+    af.changeColour_actionPerformed(JalviewColourScheme.PID.toString());
+
+    SequenceI seq = viewport.getAlignment().getSequenceAt(0);
+
+    /*
+     * including gaps, A should be coloured for 50% consensus
+     */
+    Color c = viewport
+            .getResidueShading().findColour('A', 0, seq);
+    assertEquals(c, over40);
+
+    /*
+     * now choose to ignore gaps; colour should be for 67%
+     */
+    viewport.setIgnoreGapsConsensus(true, af.alignPanel);
+    c = viewport
+            .getResidueShading().findColour('A', 0, seq);
+    assertEquals(c, over60);
+  }
+}
index d3a4fff..b45e0d3 100644 (file)
@@ -24,18 +24,26 @@ import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertTrue;
 
-import jalview.datamodel.Profile;
-import jalview.datamodel.ProfileI;
-import jalview.datamodel.Profiles;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
 import jalview.gui.JvOptionPane;
-
-import java.awt.Color;
+import jalview.io.TCoffeeScoreFile;
 
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 public class ResidueColourSchemeTest
 {
+  @BeforeClass(alwaysRun = true)
+  public void setUp()
+  {
+
+  }
 
   @BeforeClass(alwaysRun = true)
   public void setUpJvOptionPane()
@@ -45,135 +53,149 @@ public class ResidueColourSchemeTest
   }
 
   @Test(groups = "Functional")
-  public void testAboveThreshold()
+  public void testIsApplicableTo()
   {
+    SequenceI pep1 = new Sequence("pep1", "APQTWLS");
+    SequenceI pep2 = new Sequence("pep2", "AILFQYG");
+    SequenceI dna1 = new Sequence("dna1", "ACTGAC");
+    SequenceI dna2 = new Sequence("dna2", "TCCAAG");
+    AlignmentI peptide = new Alignment(new SequenceI[] { pep1, pep2 });
+    AlignmentI nucleotide = new Alignment(new SequenceI[] { dna1, dna2 });
+
     /*
-     * make up profiles for this alignment:
-     * AR-Q
-     * AR--
-     * SR-T
-     * SR-T
+     * peptide-specific colour schemes
      */
-    ProfileI[] profiles = new ProfileI[4];
-    profiles[0] = new Profile(4, 0, 2, "AS");
-    profiles[1] = new Profile(4, 0, 4, "R");
-    profiles[2] = new Profile(4, 4, 0, "");
-    profiles[3] = new Profile(4, 1, 2, "T");
-    ResidueColourScheme rcs = new ResidueColourScheme();
-    rcs.setConsensus(new Profiles(profiles));
-    
+    assertTrue(new ClustalxColourScheme(peptide, null)
+            .isApplicableTo(peptide));
+    assertFalse(new ClustalxColourScheme(nucleotide, null)
+            .isApplicableTo(nucleotide));
+    assertTrue(new Blosum62ColourScheme().isApplicableTo(peptide));
+    assertFalse(new Blosum62ColourScheme().isApplicableTo(nucleotide));
+    assertTrue(new BuriedColourScheme().isApplicableTo(peptide));
+    assertFalse(new BuriedColourScheme().isApplicableTo(nucleotide));
+    assertTrue(new HelixColourScheme().isApplicableTo(peptide));
+    assertFalse(new HelixColourScheme().isApplicableTo(nucleotide));
+    assertTrue(new HydrophobicColourScheme().isApplicableTo(peptide));
+    assertFalse(new HydrophobicColourScheme().isApplicableTo(nucleotide));
+    assertTrue(new StrandColourScheme().isApplicableTo(peptide));
+    assertFalse(new StrandColourScheme().isApplicableTo(nucleotide));
+    assertTrue(new TaylorColourScheme().isApplicableTo(peptide));
+    assertFalse(new TaylorColourScheme().isApplicableTo(nucleotide));
+    assertTrue(new TurnColourScheme().isApplicableTo(peptide));
+    assertFalse(new TurnColourScheme().isApplicableTo(nucleotide));
+    assertTrue(new ZappoColourScheme().isApplicableTo(peptide));
+    assertFalse(new ZappoColourScheme().isApplicableTo(nucleotide));
+
+    /*
+     * nucleotide-specific colour schemes
+     */
+    assertFalse(new NucleotideColourScheme().isApplicableTo(peptide));
+    assertTrue(new NucleotideColourScheme().isApplicableTo(nucleotide));
+    assertFalse(new PurinePyrimidineColourScheme().isApplicableTo(peptide));
+    assertTrue(new PurinePyrimidineColourScheme()
+            .isApplicableTo(nucleotide));
+    assertFalse(new RNAInteractionColourScheme().isApplicableTo(peptide));
+    assertTrue(new RNAInteractionColourScheme().isApplicableTo(nucleotide));
+
     /*
-     * no threshold
+     * indifferent
      */
-    rcs.setThreshold(0, true);
-    assertTrue(rcs.aboveThreshold('a', 0));
-    assertTrue(rcs.aboveThreshold('S', 0));
-    assertFalse(rcs.aboveThreshold('W', 0));
-    assertTrue(rcs.aboveThreshold('R', 1));
-    assertFalse(rcs.aboveThreshold('W', 2));
-    assertTrue(rcs.aboveThreshold('t', 3));
-    assertFalse(rcs.aboveThreshold('Q', 3));
+    assertTrue(new UserColourScheme().isApplicableTo(peptide));
+    assertTrue(new UserColourScheme().isApplicableTo(nucleotide));
+    assertTrue(new ScoreColourScheme(new int[] {}, new double[] {}, 0, 0d)
+            .isApplicableTo(peptide));
+    assertTrue(new ScoreColourScheme(new int[] {}, new double[] {}, 0, 0d)
+            .isApplicableTo(nucleotide));
+    ResidueColourScheme rcs = new PIDColourScheme();
+    assertTrue(rcs.isApplicableTo(peptide));
+    assertTrue(rcs.isApplicableTo(nucleotide));
+    assertTrue(new PIDColourScheme().isApplicableTo(peptide));
+    assertTrue(new PIDColourScheme().isApplicableTo(nucleotide));
+    assertTrue(new FollowerColourScheme().isApplicableTo(peptide));
+    assertTrue(new FollowerColourScheme().isApplicableTo(nucleotide));
 
     /*
-     * with threshold, include gaps
+     * TCoffee colour requires the presence of TCoffee score annotation
      */
-    rcs.setThreshold(60, false);
-    assertFalse(rcs.aboveThreshold('a', 0));
-    assertFalse(rcs.aboveThreshold('S', 0));
-    assertTrue(rcs.aboveThreshold('R', 1));
-    assertFalse(rcs.aboveThreshold('W', 2));
-    assertFalse(rcs.aboveThreshold('t', 3)); // 50% < 60%
+    assertFalse(new TCoffeeColourScheme(peptide).isApplicableTo(peptide));
+    assertFalse(new TCoffeeColourScheme(nucleotide)
+            .isApplicableTo(nucleotide));
+    AlignmentAnnotation aa = new AlignmentAnnotation("T-COFFEE", "", null);
+    aa.setCalcId(TCoffeeScoreFile.TCOFFEE_SCORE);
+    peptide.addAnnotation(aa);
+    aa = new AlignmentAnnotation("T-COFFEE", "", null);
+    aa.setCalcId(TCoffeeScoreFile.TCOFFEE_SCORE);
+    nucleotide.addAnnotation(aa);
+    assertTrue(new TCoffeeColourScheme(peptide).isApplicableTo(peptide));
+    assertTrue(new TCoffeeColourScheme(nucleotide)
+            .isApplicableTo(nucleotide));
 
     /*
-     * with threshold, ignore gaps
+     * RNAHelices requires the presence of rna secondary structure
      */
-    rcs.setThreshold(60, true);
-    assertFalse(rcs.aboveThreshold('a', 0));
-    assertFalse(rcs.aboveThreshold('S', 0));
-    assertTrue(rcs.aboveThreshold('R', 1));
-    assertFalse(rcs.aboveThreshold('W', 2));
-    assertTrue(rcs.aboveThreshold('t', 3)); // 67% > 60%
+    assertFalse(new RNAHelicesColour(peptide).isApplicableTo(peptide));
+    assertFalse(new RNAHelicesColour(nucleotide).isApplicableTo(nucleotide));
+    // add secondary structure (small but perfectly formed)
+    Annotation[] ss = new Annotation[2];
+    ss[0] = new Annotation("", "", '{', 0f);
+    ss[1] = new Annotation("", "", '}', 0f);
+    nucleotide.addAnnotation(new AlignmentAnnotation("SS", "", ss));
+    assertTrue(new RNAHelicesColour(nucleotide).isApplicableTo(nucleotide));
   }
 
-  /**
-   * Test colour bleaching based on conservation score and conservation slider.
-   * Scores of 10 or 11 should leave colours unchanged. Gap is always white.
-   */
   @Test(groups = "Functional")
-  public void testApplyConservation()
+  public void testIsApplicableTo_dynamicColourScheme()
   {
-    ResidueColourScheme rcs = new ResidueColourScheme();
-
-    // no conservation present - no fading
-    assertEquals(Color.RED, rcs.applyConservation(Color.RED, 12));
-    
-    // cheat by setting conservation sequence directly
-    // rather than calculating it - good enough for this test
-    String consensus = "0123456789+*-";
-    rcs.conservation = consensus.toCharArray();
-
-    // column out of range:
-    assertEquals(Color.RED,
-            rcs.applyConservation(Color.RED, consensus.length()));
-
+    SequenceI pep1 = new Sequence("pep1", "APQTWLS");
+    SequenceI pep2 = new Sequence("pep2", "AILFQYG");
+    AlignmentI peptide = new Alignment(new SequenceI[] { pep1, pep2 });
+  
     /*
-     * with 100% threshold, 'fade factor' is 
-     * (11-score)/10 * 100/20 = (11-score)/2
-     * which is >= 1 for all scores i.e. all fade to white except +, *
+     * demonstrate that we can 'plug in' a colour scheme with specified
+     * criteria for applicability; here, that there are more than 2 sequences
      */
-    rcs.setConservationInc(100);
-    assertEquals(Color.WHITE, rcs.applyConservation(Color.RED, 0));
-    assertEquals(Color.WHITE, rcs.applyConservation(Color.RED, 1));
-    assertEquals(Color.WHITE, rcs.applyConservation(Color.RED, 2));
-    assertEquals(Color.WHITE, rcs.applyConservation(Color.RED, 3));
-    assertEquals(Color.WHITE, rcs.applyConservation(Color.RED, 4));
-    assertEquals(Color.WHITE, rcs.applyConservation(Color.RED, 5));
-    assertEquals(Color.WHITE, rcs.applyConservation(Color.RED, 6));
-    assertEquals(Color.WHITE, rcs.applyConservation(Color.RED, 7));
-    assertEquals(Color.WHITE, rcs.applyConservation(Color.RED, 8));
-    assertEquals(Color.WHITE, rcs.applyConservation(Color.RED, 9));
-    assertEquals(Color.RED, rcs.applyConservation(Color.RED, 10));
-    assertEquals(Color.RED, rcs.applyConservation(Color.RED, 11));
-    assertEquals(Color.WHITE, rcs.applyConservation(Color.RED, 12));
+    ColourSchemeI cs = new UserColourScheme()
+    {
+      @Override
+      public boolean isApplicableTo(AnnotatedCollectionI ac)
+      {
+        AlignmentI al = ac.getContext() == null ? (AlignmentI) ac
+                : (AlignmentI) ac.getContext();
+        return al.getSequences().size() > 2;
+      }
+    };
+    assertFalse(cs.isApplicableTo(peptide));
+    peptide.addSequence(pep1);
+    assertTrue(cs.isApplicableTo(peptide));
+  }
 
-    /*
-     * with 0% threshold, there should be no fading
-     */
-    rcs.setConservationInc(0);
-    assertEquals(Color.RED, rcs.applyConservation(Color.RED, 0));
-    assertEquals(Color.RED, rcs.applyConservation(Color.RED, 1));
-    assertEquals(Color.RED, rcs.applyConservation(Color.RED, 2));
-    assertEquals(Color.RED, rcs.applyConservation(Color.RED, 3));
-    assertEquals(Color.RED, rcs.applyConservation(Color.RED, 4));
-    assertEquals(Color.RED, rcs.applyConservation(Color.RED, 5));
-    assertEquals(Color.RED, rcs.applyConservation(Color.RED, 6));
-    assertEquals(Color.RED, rcs.applyConservation(Color.RED, 7));
-    assertEquals(Color.RED, rcs.applyConservation(Color.RED, 8));
-    assertEquals(Color.RED, rcs.applyConservation(Color.RED, 9));
-    assertEquals(Color.RED, rcs.applyConservation(Color.RED, 10));
-    assertEquals(Color.RED, rcs.applyConservation(Color.RED, 11));
-    assertEquals(Color.WHITE, rcs.applyConservation(Color.RED, 12)); // gap
+  @Test(groups = "Functional")
+  public void testGetName()
+  {
+    SequenceI pep1 = new Sequence("pep1", "APQTWLS");
+    AlignmentI peptide = new Alignment(new SequenceI[] { pep1 });
 
-    /*
-     * with 40% threshold, 'fade factor' is 
-     * (11-score)/10 * 40/20 = (11-score)/5
-     * which is {>1, >1, >1, >1, >1, >1, 1, 0.8, 0.6, 0.4} for score 0-9
-     * e.g. score 7 colour fades 80% of the way to white (255, 255, 255)
-     */
-    rcs.setConservationInc(40);
-    Color colour = new Color(155, 105, 55);
-    assertEquals(Color.WHITE, rcs.applyConservation(colour, 0));
-    assertEquals(Color.WHITE, rcs.applyConservation(colour, 1));
-    assertEquals(Color.WHITE, rcs.applyConservation(colour, 2));
-    assertEquals(Color.WHITE, rcs.applyConservation(colour, 3));
-    assertEquals(Color.WHITE, rcs.applyConservation(colour, 4));
-    assertEquals(Color.WHITE, rcs.applyConservation(colour, 5));
-    assertEquals(Color.WHITE, rcs.applyConservation(colour, 6));
-    assertEquals(new Color(235, 225, 215), rcs.applyConservation(colour, 7));
-    assertEquals(new Color(215, 195, 175), rcs.applyConservation(colour, 8));
-    assertEquals(new Color(195, 165, 135), rcs.applyConservation(colour, 9));
-    assertEquals(colour, rcs.applyConservation(colour, 10));
-    assertEquals(colour, rcs.applyConservation(colour, 11));
-    assertEquals(Color.WHITE, rcs.applyConservation(colour, 12));
+    assertEquals("Blosum62", new Blosum62ColourScheme().getSchemeName());
+    assertEquals("Buried Index", new BuriedColourScheme().getSchemeName());
+    assertEquals("Helix Propensity", new HelixColourScheme().getSchemeName());
+    assertEquals("Hydrophobic", new HydrophobicColourScheme().getSchemeName());
+    assertEquals("Strand Propensity", new StrandColourScheme().getSchemeName());
+    assertEquals("Taylor", new TaylorColourScheme().getSchemeName());
+    assertEquals("Turn Propensity", new TurnColourScheme().getSchemeName());
+    assertEquals("Zappo", new ZappoColourScheme().getSchemeName());
+    assertEquals("Nucleotide", new NucleotideColourScheme().getSchemeName());
+    assertEquals("Purine/Pyrimidine",
+            new PurinePyrimidineColourScheme().getSchemeName());
+    assertEquals("RNA Interaction type",
+            new RNAInteractionColourScheme().getSchemeName());
+    assertEquals("User Defined", new UserColourScheme().getSchemeName());
+    assertEquals("Score", new ScoreColourScheme(new int[] {},
+            new double[] {}, 0, 0d).getSchemeName());
+    assertEquals("% Identity", new PIDColourScheme().getSchemeName());
+    assertEquals("Follower", new FollowerColourScheme().getSchemeName());
+    assertEquals("T-Coffee Scores",
+            new TCoffeeColourScheme(peptide).getSchemeName());
+    assertEquals("RNA Helices",
+            new RNAHelicesColour(peptide).getSchemeName());
   }
 }
index 645d5b8..497014e 100644 (file)
@@ -21,8 +21,6 @@
 package jalview.schemes;
 
 import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertNull;
-import static org.testng.AssertJUnit.assertSame;
 
 import jalview.gui.JvOptionPane;
 
@@ -42,40 +40,44 @@ public class UserColourSchemeTest
   }
 
   @Test(groups = "Functional")
-  public void testGetColourFromString()
+  public void testParseAppletParameter()
   {
-    /*
-     * by colour name - if known to AWT, and included in
-     * 
-     * @see ColourSchemeProperty.getAWTColorFromName()
-     */
-    assertSame(Color.RED, UserColourScheme.getColourFromString("red"));
-    assertSame(Color.RED, UserColourScheme.getColourFromString("Red"));
-    assertSame(Color.RED, UserColourScheme.getColourFromString(" RED "));
+    UserColourScheme cs = new UserColourScheme("white");
+    cs.parseAppletParameter("D,E=red; K,R,H=0022FF; c=10 , 20,30");
+    assertEquals(Color.RED, cs.findColour('D'));
+    assertEquals(Color.RED, cs.findColour('d'));
+    assertEquals(Color.RED, cs.findColour('E'));
+    assertEquals(Color.RED, cs.findColour('e'));
+    Color c1 = new Color(0x0022ff);
+    assertEquals(c1, cs.findColour('K'));
+    assertEquals(c1, cs.findColour('R'));
+    assertEquals(c1, cs.findColour('h'));
+    Color c2 = new Color(10, 20, 30);
+    assertEquals(c2, cs.findColour('c'));
 
-    /*
-     * by RGB hex code
-     */
-    String hexColour = Integer.toHexString(Color.RED.getRGB() & 0xffffff);
-    assertEquals(Color.RED, UserColourScheme.getColourFromString(hexColour));
-    // 'hex' prefixes _not_ wanted here
-    assertNull(UserColourScheme.getColourFromString("0x" + hexColour));
-    assertNull(UserColourScheme.getColourFromString("#" + hexColour));
-
-    /*
-     * by RGB triplet
-     */
-    String rgb = String.format("%d,%d,%d", Color.red.getRed(),
-            Color.red.getGreen(), Color.red.getBlue());
-    assertEquals(Color.RED, UserColourScheme.getColourFromString(rgb));
+    cs = new UserColourScheme("white");
+    cs.parseAppletParameter("D,E=red; K,R,H=0022FF; c=10 , 20,30;t=orange;lowercase=blue;s=pink");
+    assertEquals(Color.RED, cs.findColour('D'));
+    assertEquals(Color.blue, cs.findColour('d'));
+    assertEquals(Color.RED, cs.findColour('E'));
+    assertEquals(Color.blue, cs.findColour('e'));
+    assertEquals(c1, cs.findColour('K'));
+    assertEquals(c1, cs.findColour('R'));
+    assertEquals(Color.blue, cs.findColour('h'));
+    assertEquals(c2, cs.findColour('c'));
+    // 'lowercase' sets all lower-case not already set to the given colour
+    assertEquals(Color.orange, cs.findColour('t'));
+    assertEquals(Color.blue, cs.findColour('k'));
+    assertEquals(Color.blue, cs.findColour('a'));
+    assertEquals(Color.pink, cs.findColour('s'));
+  }
 
-    /*
-     * odds and ends
-     */
-    assertNull(UserColourScheme.getColourFromString(null));
-    assertNull(UserColourScheme.getColourFromString("rubbish"));
-    assertEquals(Color.WHITE, UserColourScheme.getColourFromString("-1"));
-    assertNull(UserColourScheme.getColourFromString(String
-            .valueOf(Integer.MAX_VALUE)));
+  @Test(groups = "Functional")
+  public void testToAppletParameter()
+  {
+    UserColourScheme cs = new UserColourScheme(
+            "E,D=red; K,R,H=0022FF; c=10 , 20,30");
+    String param = cs.toAppletParameter();
+    assertEquals("D,E=ff0000;H,K,R=0022ff;c=0a141e", param);
   }
 }
index b74a089..0422537 100644 (file)
@@ -24,18 +24,25 @@ import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertTrue;
 
+import jalview.api.AlignmentViewPanel;
+import jalview.api.FeatureRenderer;
+import jalview.api.SequenceRenderer;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.PDBEntry.Type;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceI;
 import jalview.gui.JvOptionPane;
 import jalview.io.DataSourceType;
+import jalview.schemes.ColourSchemeI;
 import jalview.structure.AtomSpec;
+import jalview.structure.StructureMappingcommandSet;
 import jalview.structure.StructureSelectionManager;
 import jalview.structures.models.AAStructureBindingModel.SuperposeData;
 
+import java.awt.Color;
 import java.util.Arrays;
 import java.util.List;
 
@@ -155,6 +162,59 @@ public class AAStructureBindingModelTest
       {
         return null;
       }
+
+      @Override
+      public void setJalviewColourScheme(ColourSchemeI cs)
+      {
+      }
+
+      @Override
+      public void superposeStructures(AlignmentI[] als, int[] alm,
+              ColumnSelection[] alc)
+      {
+      }
+
+      @Override
+      public void setBackgroundColour(Color col)
+      {
+      }
+
+      @Override
+      protected StructureMappingcommandSet[] getColourBySequenceCommands(
+              String[] files, SequenceRenderer sr, FeatureRenderer fr,
+              AlignmentI alignment)
+      {
+        return null;
+      }
+
+      @Override
+      public FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment)
+      {
+        return null;
+      }
+
+      @Override
+      public SequenceRenderer getSequenceRenderer(
+              AlignmentViewPanel alignment)
+      {
+        return null;
+      }
+
+      @Override
+      protected void colourBySequence(
+              StructureMappingcommandSet[] colourBySequenceCommands)
+      {
+      }
+
+      @Override
+      public void colourByChain()
+      {
+      }
+
+      @Override
+      public void colourByCharge()
+      {
+      }
     };
   }
 
@@ -239,4 +299,14 @@ public class AAStructureBindingModelTest
     assertFalse(matched[4]); // superposable, but hidden, column
     assertTrue(matched[5]);
   }
+
+  public FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment)
+  {
+    return null;
+  }
+
+  public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment)
+  {
+    return null;
+  }
 }
index 9a5d093..fa4091f 100644 (file)
@@ -166,4 +166,81 @@ public class ColorUtilsTest
     assertEquals(new Color(46, 31, 16), // with rounding down
             ColorUtils.bleachColour(colour, -0.7f));
   }
+
+  @Test(groups = "Functional")
+  public void testParseColourString()
+  {
+    /*
+     * by colour name - if known to AWT, and included in
+     * 
+     * @see ColourSchemeProperty.getAWTColorFromName()
+     */
+    assertSame(Color.RED, ColorUtils.parseColourString("red"));
+    assertSame(Color.RED, ColorUtils.parseColourString("Red"));
+    assertSame(Color.RED, ColorUtils.parseColourString(" RED "));
+
+    /*
+     * by RGB hex code
+     */
+    String hexColour = Integer.toHexString(Color.RED.getRGB() & 0xffffff);
+    assertEquals("ff0000", hexColour);
+    assertEquals(Color.RED, ColorUtils.parseColourString(hexColour));
+    // 'hex' prefixes _not_ wanted here
+    assertNull(ColorUtils.parseColourString("0x" + hexColour));
+    assertNull(ColorUtils.parseColourString("#" + hexColour));
+    // out of range, but Color constructor just or's the rgb value with 0
+    assertEquals(Color.black, ColorUtils.parseColourString("1000000"));
+
+    /*
+     * by RGB triplet
+     */
+    Color c = Color.pink;
+    String rgb = String.format("%d,%d,%d", c.getRed(), c.getGreen(),
+            c.getBlue());
+    assertEquals("255,175,175", rgb);
+    assertEquals(c, ColorUtils.parseColourString(rgb));
+    assertEquals(c, ColorUtils.parseColourString("255, 175 , 175"));
+
+    /*
+     * odds and ends
+     */
+    assertNull(ColorUtils.parseColourString(null));
+    assertNull(ColorUtils.parseColourString("rubbish"));
+    assertEquals(Color.WHITE, ColorUtils.parseColourString("-1"));
+    assertNull(ColorUtils.parseColourString(String
+            .valueOf(Integer.MAX_VALUE)));
+    assertNull(ColorUtils.parseColourString("100,200,300")); // out of range
+    assertNull(ColorUtils.parseColourString("100,200")); // too few
+    assertNull(ColorUtils.parseColourString("100,200,100,200")); // too many
+  }
+
+  @Test(groups = "Functional")
+  public void testGetAWTColorFromName() {
+    assertEquals(Color.white, ColorUtils.getAWTColorFromName("white"));
+    assertEquals(Color.white, ColorUtils.getAWTColorFromName("White"));
+    assertEquals(Color.white, ColorUtils.getAWTColorFromName("WHITE"));
+    assertEquals(Color.pink, ColorUtils.getAWTColorFromName("pink"));
+    assertNull(ColorUtils.getAWTColorFromName("mauve")); // no such name
+    assertNull(ColorUtils.getAWTColorFromName(""));
+    assertNull(ColorUtils.getAWTColorFromName(null));
+  }
+
+  @Test(groups = "Functional")
+  public void testCreateColourFromName()
+  {
+    assertEquals(Color.white, ColorUtils.createColourFromName(null));
+    assertEquals(new Color(20, 20, 20), ColorUtils.createColourFromName(""));
+    assertEquals(new Color(98, 131, 171),
+            ColorUtils.createColourFromName("None")); // no special treatment!
+    assertEquals(new Color(123, 211, 122),
+            ColorUtils.createColourFromName("hello world"));
+    assertEquals(new Color(27, 147, 112),
+            ColorUtils.createColourFromName("HELLO WORLD"));
+    /*
+     * the algorithm makes the same values for r,g,b if 
+     * the string consists of 3 repeating substrings
+     */
+    assertEquals(new Color(184, 184, 184),
+            ColorUtils.createColourFromName("HELLO HELLO HELLO "));
+  }
 }