156c517471be410e521d50861672996d154e76b4
[jalview.git] / src / jalview / appletgui / AlignViewport.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3  * Copyright (C) 2014 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.analysis.NJTree;
24 import jalview.api.AlignViewportI;
25 import jalview.bin.JalviewLite;
26 import jalview.datamodel.AlignmentI;
27 import jalview.datamodel.ColumnSelection;
28 import jalview.datamodel.Sequence;
29 import jalview.datamodel.SequenceGroup;
30 import jalview.datamodel.SequenceI;
31 import jalview.schemes.ColourSchemeProperty;
32 import jalview.schemes.UserColourScheme;
33 import jalview.structure.SelectionSource;
34 import jalview.structure.VamsasSource;
35 import jalview.viewmodel.AlignmentViewport;
36
37 import java.awt.Font;
38 import java.util.Stack;
39
40 public class AlignViewport extends AlignmentViewport implements
41         AlignViewportI, SelectionSource, VamsasSource
42 {
43   int startRes;
44
45   int endRes;
46
47   int startSeq;
48
49   int endSeq;
50
51   boolean cursorMode = false;
52
53   Font font = new Font("SansSerif", Font.PLAIN, 10);
54
55   boolean validCharWidth = true;
56
57   NJTree currentTree = null;
58
59   public jalview.bin.JalviewLite applet;
60
61   boolean MAC = false;
62
63   Stack historyList = new Stack();
64
65   Stack redoList = new Stack();
66
67   private AnnotationColumnChooser annotationColumnSelectionState;
68
69   public void finalize()
70   {
71     applet = null;
72     quality = null;
73     alignment = null;
74     colSel = null;
75   }
76
77   public AlignViewport(AlignmentI al, JalviewLite applet)
78   {
79     super();
80     calculator = new jalview.workers.AlignCalcManager();
81     this.applet = applet;
82     alignment = al;
83     // we always pad gaps
84     this.setPadGaps(true);
85     this.startRes = 0;
86     this.endRes = al.getWidth() - 1;
87     this.startSeq = 0;
88     this.endSeq = al.getHeight() - 1;
89     if (applet != null)
90     {
91       // get the width and height scaling factors if they were specified
92       String param = applet.getParameter("widthScale");
93       if (param != null)
94       {
95         try
96         {
97           widthScale = new Float(param).floatValue();
98         } catch (Exception e)
99         {
100         }
101         if (widthScale <= 1.0)
102         {
103           System.err
104                   .println("Invalid alignment character width scaling factor ("
105                           + widthScale + "). Ignoring.");
106           widthScale = 1;
107         }
108         if (applet.debug)
109         {
110           System.err
111                   .println("Alignment character width scaling factor is now "
112                           + widthScale);
113         }
114       }
115       param = applet.getParameter("heightScale");
116       if (param != null)
117       {
118         try
119         {
120           heightScale = new Float(param).floatValue();
121         } catch (Exception e)
122         {
123         }
124         if (heightScale <= 1.0)
125         {
126           System.err
127                   .println("Invalid alignment character height scaling factor ("
128                           + heightScale + "). Ignoring.");
129           heightScale = 1;
130         }
131         if (applet.debug)
132         {
133           System.err
134                   .println("Alignment character height scaling factor is now "
135                           + heightScale);
136         }
137       }
138     }
139     setFont(font);
140
141     MAC = new jalview.util.Platform().isAMac();
142
143     if (applet != null)
144     {
145       setShowJVSuffix(applet.getDefaultParameter("showFullId",
146               getShowJVSuffix()));
147
148       setShowAnnotation(applet.getDefaultParameter("showAnnotation",
149               isShowAnnotation()));
150
151       showConservation = applet.getDefaultParameter("showConservation",
152               showConservation);
153
154       showQuality = applet.getDefaultParameter("showQuality", showQuality);
155
156       showConsensus = applet.getDefaultParameter("showConsensus",
157               showConsensus);
158
159       setShowUnconserved(applet.getDefaultParameter("showUnconserved",
160               getShowUnconserved()));
161
162       String param = applet.getParameter("upperCase");
163       if (param != null)
164       {
165         if (param.equalsIgnoreCase("bold"))
166         {
167           setUpperCasebold(true);
168         }
169       }
170       sortByTree = applet.getDefaultParameter("sortByTree", sortByTree);
171
172       followHighlight = applet.getDefaultParameter("automaticScrolling",
173               followHighlight);
174       followSelection = followHighlight;
175
176       showSequenceLogo = applet.getDefaultParameter("showSequenceLogo",
177               showSequenceLogo);
178
179       normaliseSequenceLogo = applet.getDefaultParameter(
180               "normaliseSequenceLogo", applet.getDefaultParameter(
181                       "normaliseLogo", normaliseSequenceLogo));
182
183       showGroupConsensus = applet.getDefaultParameter("showGroupConsensus",
184               showGroupConsensus);
185
186       showGroupConservation = applet.getDefaultParameter(
187               "showGroupConservation", showGroupConservation);
188
189       showConsensusHistogram = applet.getDefaultParameter(
190               "showConsensusHistogram", showConsensusHistogram);
191
192     }
193
194     if (applet != null)
195     {
196       String colour = applet.getParameter("defaultColour");
197
198       if (colour == null)
199       {
200         colour = applet.getParameter("userDefinedColour");
201         if (colour != null)
202         {
203           colour = "User Defined";
204         }
205       }
206
207       if (colour != null)
208       {
209         globalColourScheme = ColourSchemeProperty.getColour(alignment,
210                 colour);
211         if (globalColourScheme != null)
212         {
213           globalColourScheme.setConsensus(hconsensus);
214         }
215       }
216
217       if (applet.getParameter("userDefinedColour") != null)
218       {
219         ((UserColourScheme) globalColourScheme).parseAppletParameter(applet
220                 .getParameter("userDefinedColour"));
221       }
222     }
223     initAutoAnnotation();
224
225   }
226
227   /**
228    * get the consensus sequence as displayed under the PID consensus annotation
229    * row.
230    * 
231    * @return consensus sequence as a new sequence object
232    */
233   public SequenceI getConsensusSeq()
234   {
235     if (consensus == null)
236     {
237       updateConsensus(null);
238     }
239     if (consensus == null)
240     {
241       return null;
242     }
243     StringBuffer seqs = new StringBuffer();
244     for (int i = 0; i < consensus.annotations.length; i++)
245     {
246       if (consensus.annotations[i] != null)
247       {
248         if (consensus.annotations[i].description.charAt(0) == '[')
249         {
250           seqs.append(consensus.annotations[i].description.charAt(1));
251         }
252         else
253         {
254           seqs.append(consensus.annotations[i].displayCharacter);
255         }
256       }
257     }
258     SequenceI sq = new Sequence("Consensus", seqs.toString());
259     sq.setDescription("Percentage Identity Consensus "
260             + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
261     return sq;
262   }
263
264   public int getStartRes()
265   {
266     return startRes;
267   }
268
269   public int getEndRes()
270   {
271     return endRes;
272   }
273
274   public int getStartSeq()
275   {
276     return startSeq;
277   }
278
279   public void setStartRes(int res)
280   {
281     this.startRes = res;
282   }
283
284   public void setStartSeq(int seq)
285   {
286     this.startSeq = seq;
287   }
288
289   public void setEndRes(int res)
290   {
291     if (res > alignment.getWidth() - 1)
292     {
293       // log.System.out.println(" Corrected res from " + res + " to maximum " +
294       // (alignment.getWidth()-1));
295       res = alignment.getWidth() - 1;
296     }
297     if (res < 0)
298     {
299       res = 0;
300     }
301     this.endRes = res;
302   }
303
304   public void setEndSeq(int seq)
305   {
306     if (seq > alignment.getHeight())
307     {
308       seq = alignment.getHeight();
309     }
310     if (seq < 0)
311     {
312       seq = 0;
313     }
314     this.endSeq = seq;
315   }
316
317   public int getEndSeq()
318   {
319     return endSeq;
320   }
321
322   java.awt.Frame nullFrame;
323
324   protected FeatureSettings featureSettings = null;
325
326   private float heightScale = 1, widthScale = 1;
327
328   public void setFont(Font f)
329   {
330     font = f;
331     if (nullFrame == null)
332     {
333       nullFrame = new java.awt.Frame();
334       nullFrame.addNotify();
335     }
336
337     java.awt.FontMetrics fm = nullFrame.getGraphics().getFontMetrics(font);
338     setCharHeight((int) (heightScale * fm.getHeight()));
339     setCharWidth((int) (widthScale * fm.charWidth('M')));
340
341     if (isUpperCasebold())
342     {
343       Font f2 = new Font(f.getName(), Font.BOLD, f.getSize());
344       fm = nullFrame.getGraphics().getFontMetrics(f2);
345       setCharWidth((int) (widthScale * (fm.stringWidth("MMMMMMMMMMM") / 10)));
346     }
347   }
348
349   public Font getFont()
350   {
351     return font;
352   }
353
354
355   public void resetSeqLimits(int height)
356   {
357     setEndSeq(height / getCharHeight());
358   }
359
360   public void setCurrentTree(NJTree tree)
361   {
362     currentTree = tree;
363   }
364
365   public NJTree getCurrentTree()
366   {
367     return currentTree;
368   }
369
370
371   boolean centreColumnLabels;
372
373   public boolean getCentreColumnLabels()
374   {
375     return centreColumnLabels;
376   }
377
378   public boolean followHighlight = true;
379
380   public boolean getFollowHighlight()
381   {
382     return followHighlight;
383   }
384
385   public boolean followSelection = true;
386
387   /**
388    * @return true if view selection should always follow the selections
389    *         broadcast by other selection sources
390    */
391   public boolean getFollowSelection()
392   {
393     return followSelection;
394   }
395
396   public void sendSelection()
397   {
398     jalview.structure.StructureSelectionManager
399             .getStructureSelectionManager(applet).sendSelection(
400                     new SequenceGroup(getSelectionGroup()),
401                     new ColumnSelection(getColumnSelection()), this);
402   }
403
404   /**
405    * synthesize a column selection if none exists so it covers the given
406    * selection group. if wholewidth is false, no column selection is made if the
407    * selection group covers the whole alignment width.
408    * 
409    * @param sg
410    * @param wholewidth
411    */
412   public void expandColSelection(SequenceGroup sg, boolean wholewidth)
413   {
414     int sgs, sge;
415     if (sg != null
416             && (sgs = sg.getStartRes()) >= 0
417             && sg.getStartRes() <= (sge = sg.getEndRes())
418             && (colSel == null || colSel.getSelected() == null || colSel
419                     .getSelected().size() == 0))
420     {
421       if (!wholewidth && alignment.getWidth() == (1 + sge - sgs))
422       {
423         // do nothing
424         return;
425       }
426       if (colSel == null)
427       {
428         colSel = new ColumnSelection();
429       }
430       for (int cspos = sg.getStartRes(); cspos <= sg.getEndRes(); cspos++)
431       {
432         colSel.addElement(cspos);
433       }
434     }
435   }
436
437   public boolean isNormaliseSequenceLogo()
438   {
439     return normaliseSequenceLogo;
440   }
441
442   public void setNormaliseSequenceLogo(boolean state)
443   {
444     normaliseSequenceLogo = state;
445   }
446
447   /**
448    * 
449    * @return true if alignment characters should be displayed
450    */
451   public boolean isValidCharWidth()
452   {
453     return validCharWidth;
454   }
455
456   public AnnotationColumnChooser getAnnotationColumnSelectionState()
457   {
458     return annotationColumnSelectionState;
459   }
460
461   public void setAnnotationColumnSelectionState(
462           AnnotationColumnChooser annotationColumnSelectionState)
463   {
464     this.annotationColumnSelectionState = annotationColumnSelectionState;
465   }
466
467 }