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