JAL-3675 release notes for JAL-3750 JAL-3751
[jalview.git] / src / jalview / appletgui / AlignViewport.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.appletgui;
22
23 import jalview.api.AlignViewportI;
24 import jalview.api.FeatureSettingsModelI;
25 import jalview.bin.JalviewLite;
26 import jalview.commands.CommandI;
27 import jalview.datamodel.AlignmentI;
28 import jalview.datamodel.ColumnSelection;
29 import jalview.datamodel.HiddenColumns;
30 import jalview.datamodel.SearchResults;
31 import jalview.datamodel.SearchResultsI;
32 import jalview.datamodel.SequenceGroup;
33 import jalview.renderer.ResidueShader;
34 import jalview.schemes.ColourSchemeProperty;
35 import jalview.schemes.UserColourScheme;
36 import jalview.structure.SelectionSource;
37 import jalview.structure.StructureSelectionManager;
38 import jalview.structure.VamsasSource;
39 import jalview.viewmodel.AlignmentViewport;
40
41 import java.awt.Font;
42 import java.awt.FontMetrics;
43
44 public class AlignViewport extends AlignmentViewport
45         implements SelectionSource
46 {
47   boolean cursorMode = false;
48
49   Font font = new Font("SansSerif", Font.PLAIN, 10);
50
51   boolean validCharWidth = true;
52
53   public jalview.bin.JalviewLite applet;
54
55   boolean MAC = false;
56
57   private AnnotationColumnChooser annotationColumnSelectionState;
58
59   public AlignViewport(AlignmentI al, JalviewLite applet)
60   {
61     super(al);
62     calculator = new jalview.workers.AlignCalcManager();
63     this.applet = applet;
64
65     // we always pad gaps
66     this.setPadGaps(true);
67
68     if (applet != null)
69     {
70       // get the width and height scaling factors if they were specified
71       String param = applet.getParameter("widthScale");
72       if (param != null)
73       {
74         try
75         {
76           widthScale = Float.valueOf(param).floatValue();
77         } catch (Exception e)
78         {
79         }
80         if (widthScale <= 1.0)
81         {
82           System.err.println(
83                   "Invalid alignment character width scaling factor ("
84                           + widthScale + "). Ignoring.");
85           widthScale = 1;
86         }
87         if (JalviewLite.debug)
88         {
89           System.err.println(
90                   "Alignment character width scaling factor is now "
91                           + widthScale);
92         }
93       }
94       param = applet.getParameter("heightScale");
95       if (param != null)
96       {
97         try
98         {
99           heightScale = Float.valueOf(param).floatValue();
100         } catch (Exception e)
101         {
102         }
103         if (heightScale <= 1.0)
104         {
105           System.err.println(
106                   "Invalid alignment character height scaling factor ("
107                           + heightScale + "). Ignoring.");
108           heightScale = 1;
109         }
110         if (JalviewLite.debug)
111         {
112           System.err.println(
113                   "Alignment character height scaling factor is now "
114                           + heightScale);
115         }
116       }
117     }
118     setFont(font, true);
119
120     MAC = new jalview.util.Platform().isAMac();
121
122     if (applet != null)
123     {
124       setShowJVSuffix(
125               applet.getDefaultParameter("showFullId", getShowJVSuffix()));
126
127       setShowAnnotation(applet.getDefaultParameter("showAnnotation",
128               isShowAnnotation()));
129
130       showConservation = applet.getDefaultParameter("showConservation",
131               showConservation);
132
133       showQuality = applet.getDefaultParameter("showQuality", showQuality);
134
135       showConsensus = applet.getDefaultParameter("showConsensus",
136               showConsensus);
137
138       showOccupancy = applet.getDefaultParameter("showOccupancy",
139               showOccupancy);
140
141       setShowUnconserved(applet.getDefaultParameter("showUnconserved",
142               getShowUnconserved()));
143
144       setScaleProteinAsCdna(applet.getDefaultParameter("scaleProteinAsCdna",
145               isScaleProteinAsCdna()));
146
147       String param = applet.getParameter("upperCase");
148       if (param != null)
149       {
150         if (param.equalsIgnoreCase("bold"))
151         {
152           setUpperCasebold(true);
153         }
154       }
155       sortByTree = applet.getDefaultParameter("sortByTree", sortByTree);
156
157       setFollowHighlight(applet.getDefaultParameter("automaticScrolling",
158               isFollowHighlight()));
159       followSelection = isFollowHighlight();
160
161       showSequenceLogo = applet.getDefaultParameter("showSequenceLogo",
162               showSequenceLogo);
163
164       normaliseSequenceLogo = applet.getDefaultParameter(
165               "normaliseSequenceLogo", applet.getDefaultParameter(
166                       "normaliseLogo", normaliseSequenceLogo));
167
168       showGroupConsensus = applet.getDefaultParameter("showGroupConsensus",
169               showGroupConsensus);
170
171       showGroupConservation = applet.getDefaultParameter(
172               "showGroupConservation", showGroupConservation);
173
174       showConsensusHistogram = applet.getDefaultParameter(
175               "showConsensusHistogram", showConsensusHistogram);
176
177     }
178
179     if (applet != null)
180     {
181       String colour = al.isNucleotide()
182               ? applet.getParameter("defaultColourNuc")
183               : applet.getParameter("defaultColourProt");
184       if (colour == null)
185       {
186         colour = applet.getParameter("defaultColour");
187       }
188       if (colour == null)
189       {
190         colour = applet.getParameter("userDefinedColour");
191         if (colour != null)
192         {
193           colour = "User Defined";
194         }
195       }
196
197       if (colour != null)
198       {
199         residueShading = new ResidueShader(
200                 ColourSchemeProperty.getColourScheme(this, alignment,
201                         colour));
202         if (residueShading != null)
203         {
204           residueShading.setConsensus(hconsensus);
205         }
206       }
207
208       if (applet.getParameter("userDefinedColour") != null)
209       {
210         residueShading = new ResidueShader(new UserColourScheme(
211                 applet.getParameter("userDefinedColour")));
212       }
213     }
214     initAutoAnnotation();
215
216   }
217
218   java.awt.Frame nullFrame;
219
220   protected FeatureSettings featureSettings = null;
221
222   private float heightScale = 1, widthScale = 1;
223
224   /**
225    * {@inheritDoc}
226    */
227   @Override
228   public void setFont(Font f, boolean setGrid)
229   {
230     font = f;
231     if (nullFrame == null)
232     {
233       nullFrame = new java.awt.Frame();
234       nullFrame.addNotify();
235     }
236
237     if (setGrid)
238     {
239       FontMetrics fm = nullFrame.getGraphics().getFontMetrics(font);
240       setCharHeight((int) (heightScale * fm.getHeight()));
241       setCharWidth((int) (widthScale * fm.charWidth('M')));
242     }
243
244     if (isUpperCasebold())
245     {
246       Font f2 = new Font(f.getName(), Font.BOLD, f.getSize());
247       FontMetrics fm = nullFrame.getGraphics().getFontMetrics(f2);
248       setCharWidth(
249               (int) (widthScale * (fm.stringWidth("MMMMMMMMMMM") / 10)));
250     }
251   }
252
253   public Font getFont()
254   {
255     return font;
256   }
257
258   public void resetSeqLimits(int height)
259   {
260     ranges.setEndSeq(height / getCharHeight());
261   }
262
263   boolean centreColumnLabels;
264
265   public boolean getCentreColumnLabels()
266   {
267     return centreColumnLabels;
268   }
269
270   public boolean followSelection = true;
271
272   /**
273    * @return true if view selection should always follow the selections
274    *         broadcast by other selection sources
275    */
276   public boolean getFollowSelection()
277   {
278     return followSelection;
279   }
280
281   @Override
282   public void sendSelection()
283   {
284     getStructureSelectionManager().sendSelection(
285             new SequenceGroup(getSelectionGroup()),
286             new ColumnSelection(getColumnSelection()),
287             new HiddenColumns(getAlignment().getHiddenColumns()), this);
288   }
289
290   /**
291    * Returns an instance of the StructureSelectionManager scoped to this applet
292    * instance.
293    * 
294    * @return
295    */
296   @Override
297   public StructureSelectionManager getStructureSelectionManager()
298   {
299     return jalview.structure.StructureSelectionManager
300             .getStructureSelectionManager(applet);
301   }
302
303   @Override
304   public boolean isNormaliseSequenceLogo()
305   {
306     return normaliseSequenceLogo;
307   }
308
309   public void setNormaliseSequenceLogo(boolean state)
310   {
311     normaliseSequenceLogo = state;
312   }
313
314   /**
315    * 
316    * @return true if alignment characters should be displayed
317    */
318   @Override
319   public boolean isValidCharWidth()
320   {
321     return validCharWidth;
322   }
323
324   public AnnotationColumnChooser getAnnotationColumnSelectionState()
325   {
326     return annotationColumnSelectionState;
327   }
328
329   public void setAnnotationColumnSelectionState(
330           AnnotationColumnChooser annotationColumnSelectionState)
331   {
332     this.annotationColumnSelectionState = annotationColumnSelectionState;
333   }
334
335   @Override
336   public void mirrorCommand(CommandI command, boolean undo,
337           StructureSelectionManager ssm, VamsasSource source)
338   {
339     // TODO refactor so this can be pulled up to superclass or controller
340     /*
341      * Do nothing unless we are a 'complement' of the source. May replace this
342      * with direct calls not via SSM.
343      */
344     if (source instanceof AlignViewportI
345             && ((AlignViewportI) source).getCodingComplement() == this)
346     {
347       // ok to continue;
348     }
349     else
350     {
351       return;
352     }
353
354     CommandI mappedCommand = ssm.mapCommand(command, undo, getAlignment(),
355             getGapCharacter());
356     if (mappedCommand != null)
357     {
358       mappedCommand.doCommand(null);
359       firePropertyChange("alignment", null, getAlignment().getSequences());
360
361       // ap.scalePanelHolder.repaint();
362       // ap.repaint();
363     }
364   }
365
366   @Override
367   public VamsasSource getVamsasSource()
368   {
369     return this;
370   }
371
372   /**
373    * If this viewport has a (Protein/cDNA) complement, then scroll the
374    * complementary alignment to match this one.
375    */
376   public void scrollComplementaryAlignment(AlignmentPanel complementPanel)
377   {
378     if (complementPanel == null)
379     {
380       return;
381     }
382
383     /*
384      * Populate a SearchResults object with the mapped location to scroll to. If
385      * there is no complement, or it is not following highlights, or no mapping
386      * is found, the result will be empty.
387      */
388     SearchResultsI sr = new SearchResults();
389     int seqOffset = findComplementScrollTarget(sr);
390     if (!sr.isEmpty())
391     {
392       complementPanel.setToScrollComplementPanel(false);
393       complementPanel.scrollToCentre(sr, seqOffset);
394       complementPanel.setToScrollComplementPanel(true);
395     }
396   }
397
398   /**
399    * Applies the supplied feature settings descriptor to currently known features.
400    * This supports an 'initial configuration' of feature colouring based on a
401    * preset or user favourite. This may then be modified in the usual way using
402    * the Feature Settings dialogue. NOT IMPLEMENTED FOR APPLET
403    * 
404    * @param featureSettings
405    */
406   @Override
407   public void applyFeaturesStyle(FeatureSettingsModelI featureSettings)
408   {
409     // TODO implement for applet
410   }
411
412   /**
413    * Merges the supplied feature settings descriptor with existing feature styles.
414    * This supports an 'initial configuration' of feature colouring based on a
415    * preset or user favourite. This may then be modified in the usual way using
416    * the Feature Settings dialogue. NOT IMPLEMENTED FOR APPLET
417    * 
418    * @param featureSettings
419    */
420   @Override
421   public void mergeFeaturesStyle(FeatureSettingsModelI featureSettings)
422   {
423     // TODO Auto-generated method stub
424
425   }
426 }