JAL-3210 Improvements to eclipse detection. New src tree and SwingJS updated from...
[jalview.git] / src / jalview / schemes / ColourSchemes.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.schemes;
22
23 import jalview.api.AlignViewportI;
24 import jalview.bin.ApplicationSingletonProvider;
25 import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
26 import jalview.datamodel.AnnotatedCollectionI;
27 import jalview.datamodel.SequenceCollectionI;
28 import jalview.datamodel.SequenceI;
29 import jalview.util.ColorUtils;
30
31 import java.awt.Color;
32 import java.util.LinkedHashMap;
33 import java.util.Map;
34
35 public class ColourSchemes implements ApplicationSingletonI
36 {
37
38   /**
39    * Returns the singleton instance of this class
40    * 
41    * @return
42    */
43   public static ColourSchemes getInstance()
44   {
45     return (ColourSchemes) ApplicationSingletonProvider
46             .getInstance(ColourSchemes.class);
47   }
48
49   private ColourSchemes()
50   {
51     loadColourSchemes();
52   }
53
54   /**
55    * ColourSchemeProperty "static"
56    */
57   public Color[] rnaHelices = null;
58
59   /**
60    * delete the existing cached RNA helices colours
61    */
62   public static void resetRnaHelicesShading()
63   {
64     getInstance().rnaHelices = null;
65   }
66
67   public static void initRnaHelicesShading(int n)
68   {
69     int i = 0;
70     ColourSchemes j = getInstance();
71
72     if (j.rnaHelices == null)
73     {
74       j.rnaHelices = new Color[n + 1];
75     }
76     else if (j.rnaHelices != null && j.rnaHelices.length <= n)
77     {
78       Color[] t = new Color[n + 1];
79       System.arraycopy(j.rnaHelices, 0, t, 0, j.rnaHelices.length);
80       i = j.rnaHelices.length;
81       j.rnaHelices = t;
82     }
83     else
84     {
85       return;
86     }
87     // Generate random colors and store
88     for (; i <= n; i++)
89     {
90       j.rnaHelices[i] = ColorUtils.generateRandomColor(Color.white);
91     }
92   }
93
94   /**
95    * a map from scheme name (lower-cased) to an instance of it
96    */
97   private Map<String, ColourSchemeI> schemes;
98
99   /**
100    * Loads an instance of each standard or user-defined colour scheme
101    * 
102    * @return
103    */
104   void loadColourSchemes()
105   {
106     /*
107      * store in an order-preserving map, so items can be added to menus 
108      * in the order in which they are 'discovered'
109      */
110     schemes = new LinkedHashMap<>();
111
112     for (JalviewColourScheme cs : JalviewColourScheme.values())
113     {
114       try
115       {
116         registerColourScheme(cs.getSchemeClass().newInstance());
117       } catch (InstantiationException | IllegalAccessException e)
118       {
119         System.err.println("Error instantiating colour scheme for "
120                 + cs.toString() + " " + e.getMessage());
121         e.printStackTrace();
122       }
123     }
124   }
125
126   /**
127    * Registers a colour scheme
128    * 
129    * @param cs
130    */
131   public void registerColourScheme(ColourSchemeI cs)
132   {
133     String name = cs.getSchemeName();
134     if (name == null)
135     {
136       System.err.println("ColourScheme name may not be null");
137       return;
138     }
139
140     /*
141      * name is lower-case for non-case-sensitive lookup
142      * (name in the colour keeps its true case)
143      */
144     String lower = name.toLowerCase();
145     if (schemes.containsKey(lower))
146     {
147       System.err
148               .println("Warning: overwriting colour scheme named " + name);
149     }
150     schemes.put(lower, cs);
151   }
152
153   /**
154    * Removes a colour scheme by name
155    * 
156    * @param name
157    */
158   public void removeColourScheme(String name)
159   {
160     if (name != null)
161     {
162       schemes.remove(name.toLowerCase());
163     }
164   }
165
166   /**
167    * Returns an instance of the colour scheme with which the given view may be
168    * coloured
169    * 
170    * @param name
171    *          name of the colour scheme
172    * @param viewport
173    * @param forData
174    *          the data to be coloured
175    * @param optional
176    *          map from hidden representative sequences to the sequences they
177    *          represent
178    * @return
179    */
180   public ColourSchemeI getColourScheme(String name,
181           AlignViewportI viewport, AnnotatedCollectionI forData,
182           Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
183   {
184     if (name == null)
185     {
186       return null;
187     }
188     ColourSchemeI cs = schemes.get(name.toLowerCase());
189     return cs == null ? null
190             : cs.getInstance(viewport, forData);
191   }
192
193   /**
194    * Returns an instance of the colour scheme with which the given view may be
195    * coloured
196    * 
197    * @param name
198    *          name of the colour scheme
199    * @param forData
200    *          the data to be coloured
201    * @return
202    */
203   public ColourSchemeI getColourScheme(String name,
204           AnnotatedCollectionI forData)
205   {
206     return getColourScheme(name, null, forData, null);
207   }
208
209   /**
210    * Returns an iterable set of the colour schemes, in the order in which they
211    * were added
212    * 
213    * @return
214    */
215   public Iterable<ColourSchemeI> getColourSchemes()
216   {
217     return schemes.values();
218   }
219
220   /**
221    * Answers true if there is a scheme with the given name, else false. The test
222    * is not case-sensitive.
223    * 
224    * @param name
225    * @return
226    */
227   public boolean nameExists(String name)
228   {
229     if (name == null)
230     {
231       return false;
232     }
233     return schemes.containsKey(name.toLowerCase());
234   }
235 }