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