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