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