JAL-1807 test3 bob changes "twice"
[jalviewjs.git] / unused / appletgui / AlignViewport.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)\r
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors\r
4  * \r
5  * This file is part of Jalview.\r
6  * \r
7  * Jalview is free software: you can redistribute it and/or\r
8  * modify it under the terms of the GNU General Public License \r
9  * as published by the Free Software Foundation, either version 3\r
10  * of the License, or (at your option) any later version.\r
11  *  \r
12  * Jalview is distributed in the hope that it will be useful, but \r
13  * WITHOUT ANY WARRANTY; without even the implied warranty \r
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR \r
15  * PURPOSE.  See the GNU General Public License for more details.\r
16  * \r
17  * You should have received a copy of the GNU General Public License\r
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.\r
19  * The Jalview Authors are detailed in the 'AUTHORS' file.\r
20  */\r
21 package jalview.appletgui;\r
22 \r
23 import jalview.analysis.NJTree;\r
24 import jalview.api.AlignViewportI;\r
25 import jalview.bin.JalviewLite;\r
26 import jalview.commands.CommandI;\r
27 import jalview.datamodel.AlignmentI;\r
28 import jalview.datamodel.ColumnSelection;\r
29 import jalview.datamodel.SearchResults;\r
30 import jalview.datamodel.Sequence;\r
31 import jalview.datamodel.SequenceGroup;\r
32 import jalview.datamodel.SequenceI;\r
33 import jalview.schemes.ColourSchemeProperty;\r
34 import jalview.schemes.UserColourScheme;\r
35 import jalview.structure.CommandListener;\r
36 import jalview.structure.SelectionSource;\r
37 import jalview.structure.StructureSelectionManager;\r
38 import jalview.structure.VamsasSource;\r
39 import jalview.util.Platform;\r
40 import jalview.viewmodel.AlignmentViewport;\r
41 import jalview.workers.AlignCalcManager;\r
42 \r
43 import java.awt.Font;\r
44 \r
45 public class AlignViewport extends AlignmentViewport implements\r
46         SelectionSource, VamsasSource, CommandListener\r
47 {\r
48   boolean cursorMode = false;\r
49 \r
50   Font font = new Font("SansSerif", Font.PLAIN, 10);\r
51 \r
52   boolean validCharWidth = true;\r
53 \r
54   NJTree currentTree = null;\r
55 \r
56   public JalviewLite applet;\r
57 \r
58   boolean MAC = false;\r
59 \r
60   private AnnotationColumnChooser annotationColumnSelectionState;\r
61 \r
62   public void finalize()\r
63   {\r
64     applet = null;\r
65     quality = null;\r
66     alignment = null;\r
67     colSel = null;\r
68   }\r
69 \r
70   public AlignViewport(AlignmentI al, JalviewLite applet)\r
71   {\r
72     super();\r
73     calculator = new AlignCalcManager();\r
74     this.applet = applet;\r
75     alignment = al;\r
76     // we always pad gaps\r
77     this.setPadGaps(true);\r
78     this.startRes = 0;\r
79     this.endRes = al.getWidth() - 1;\r
80     this.startSeq = 0;\r
81     this.endSeq = al.getHeight() - 1;\r
82     if (applet != null)\r
83     {\r
84       // get the width and height scaling factors if they were specified\r
85       String param = applet.getParameter("widthScale");\r
86       if (param != null)\r
87       {\r
88         try\r
89         {\r
90           widthScale = new Float(param).floatValue();\r
91         } catch (Exception e)\r
92         {\r
93         }\r
94         if (widthScale <= 1.0)\r
95         {\r
96           System.err\r
97                   .println("Invalid alignment character width scaling factor ("\r
98                           + widthScale + "). Ignoring.");\r
99           widthScale = 1;\r
100         }\r
101         if (JalviewLite.debug)\r
102         {\r
103           System.err\r
104                   .println("Alignment character width scaling factor is now "\r
105                           + widthScale);\r
106         }\r
107       }\r
108       param = applet.getParameter("heightScale");\r
109       if (param != null)\r
110       {\r
111         try\r
112         {\r
113           heightScale = new Float(param).floatValue();\r
114         } catch (Exception e)\r
115         {\r
116         }\r
117         if (heightScale <= 1.0)\r
118         {\r
119           System.err\r
120                   .println("Invalid alignment character height scaling factor ("\r
121                           + heightScale + "). Ignoring.");\r
122           heightScale = 1;\r
123         }\r
124         if (JalviewLite.debug)\r
125         {\r
126           System.err\r
127                   .println("Alignment character height scaling factor is now "\r
128                           + heightScale);\r
129         }\r
130       }\r
131     }\r
132     setFont(font);\r
133 \r
134     MAC = Platform.isAMac();\r
135 \r
136     if (applet != null)\r
137     {\r
138       setShowJVSuffix(applet.getDefaultParameter("showFullId",\r
139               getShowJVSuffix()));\r
140 \r
141       setShowAnnotation(applet.getDefaultParameter("showAnnotation",\r
142               isShowAnnotation()));\r
143 \r
144       showConservation = applet.getDefaultParameter("showConservation",\r
145               showConservation);\r
146 \r
147       showQuality = applet.getDefaultParameter("showQuality", showQuality);\r
148 \r
149       showConsensus = applet.getDefaultParameter("showConsensus",\r
150               showConsensus);\r
151 \r
152       setShowUnconserved(applet.getDefaultParameter("showUnconserved",\r
153               getShowUnconserved()));\r
154 \r
155       setScaleProteinAsCdna(applet.getDefaultParameter(\r
156               "scaleProteinAsCdna", isScaleProteinAsCdna()));\r
157 \r
158       String param = applet.getParameter("upperCase");\r
159       if (param != null)\r
160       {\r
161         if (param.equalsIgnoreCase("bold"))\r
162         {\r
163           setUpperCasebold(true);\r
164         }\r
165       }\r
166       sortByTree = applet.getDefaultParameter("sortByTree", sortByTree);\r
167 \r
168       setFollowHighlight(applet.getDefaultParameter("automaticScrolling",\r
169               isFollowHighlight()));\r
170       followSelection = isFollowHighlight();\r
171 \r
172       showSequenceLogo = applet.getDefaultParameter("showSequenceLogo",\r
173               showSequenceLogo);\r
174 \r
175       normaliseSequenceLogo = applet.getDefaultParameter(\r
176               "normaliseSequenceLogo", applet.getDefaultParameter(\r
177                       "normaliseLogo", normaliseSequenceLogo));\r
178 \r
179       showGroupConsensus = applet.getDefaultParameter("showGroupConsensus",\r
180               showGroupConsensus);\r
181 \r
182       showGroupConservation = applet.getDefaultParameter(\r
183               "showGroupConservation", showGroupConservation);\r
184 \r
185       showConsensusHistogram = applet.getDefaultParameter(\r
186               "showConsensusHistogram", showConsensusHistogram);\r
187 \r
188     }\r
189 \r
190     if (applet != null)\r
191     {\r
192       String colour = applet.getParameter("defaultColour");\r
193 \r
194       if (colour == null)\r
195       {\r
196         colour = applet.getParameter("userDefinedColour");\r
197         if (colour != null)\r
198         {\r
199           colour = "User Defined";\r
200         }\r
201       }\r
202 \r
203       if (colour != null)\r
204       {\r
205         globalColourScheme = ColourSchemeProperty.getColour(alignment,\r
206                 colour);\r
207         if (globalColourScheme != null)\r
208         {\r
209           globalColourScheme.setConsensus(hconsensus);\r
210         }\r
211       }\r
212 \r
213       if (applet.getParameter("userDefinedColour") != null)\r
214       {\r
215         ((UserColourScheme) globalColourScheme).parseAppletParameter(applet\r
216                 .getParameter("userDefinedColour"));\r
217       }\r
218     }\r
219     initAutoAnnotation();\r
220 \r
221   }\r
222 \r
223   /**\r
224    * get the consensus sequence as displayed under the PID consensus annotation\r
225    * row.\r
226    * \r
227    * @return consensus sequence as a new sequence object\r
228    */\r
229   public SequenceI getConsensusSeq()\r
230   {\r
231     if (consensus == null)\r
232     {\r
233       updateConsensus(null);\r
234     }\r
235     if (consensus == null)\r
236     {\r
237       return null;\r
238     }\r
239     StringBuilder seqs = new StringBuilder(consensus.annotations.length);\r
240     for (int i = 0; i < consensus.annotations.length; i++)\r
241     {\r
242       if (consensus.annotations[i] != null)\r
243       {\r
244         if (consensus.annotations[i].description.charAt(0) == '[')\r
245         {\r
246           seqs.append(consensus.annotations[i].description.charAt(1));\r
247         }\r
248         else\r
249         {\r
250           seqs.append(consensus.annotations[i].displayCharacter);\r
251         }\r
252       }\r
253     }\r
254     SequenceI sq = new Sequence("Consensus", seqs.toString());\r
255     sq.setDescription("Percentage Identity Consensus "\r
256             + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));\r
257     return sq;\r
258   }\r
259 \r
260   java.awt.Frame nullFrame;\r
261 \r
262   protected FeatureSettings featureSettings = null;\r
263 \r
264   private float heightScale = 1, widthScale = 1;\r
265 \r
266   public void setFont(Font f)\r
267   {\r
268     font = f;\r
269     if (nullFrame == null)\r
270     {\r
271       nullFrame = new java.awt.Frame();\r
272       nullFrame.addNotify();\r
273     }\r
274 \r
275     java.awt.FontMetrics fm = nullFrame.getGraphics().getFontMetrics(font);\r
276     setCharHeight((int) (heightScale * fm.getHeight()));\r
277     setCharWidth((int) (widthScale * fm.charWidth('M')));\r
278 \r
279     if (isUpperCasebold())\r
280     {\r
281       Font f2 = new Font(f.getName(), Font.BOLD, f.getSize());\r
282       fm = nullFrame.getGraphics().getFontMetrics(f2);\r
283       setCharWidth((int) (widthScale * (fm.stringWidth("MMMMMMMMMMM") / 10)));\r
284     }\r
285   }\r
286 \r
287   public Font getFont()\r
288   {\r
289     return font;\r
290   }\r
291 \r
292 \r
293   public void resetSeqLimits(int height)\r
294   {\r
295     setEndSeq(height / getCharHeight());\r
296   }\r
297 \r
298   public void setCurrentTree(NJTree tree)\r
299   {\r
300     currentTree = tree;\r
301   }\r
302 \r
303   public NJTree getCurrentTree()\r
304   {\r
305     return currentTree;\r
306   }\r
307 \r
308 \r
309   boolean centreColumnLabels;\r
310 \r
311   public boolean getCentreColumnLabels()\r
312   {\r
313     return centreColumnLabels;\r
314   }\r
315 \r
316   public boolean followSelection = true;\r
317 \r
318   /**\r
319    * @return true if view selection should always follow the selections\r
320    *         broadcast by other selection sources\r
321    */\r
322   public boolean getFollowSelection()\r
323   {\r
324     return followSelection;\r
325   }\r
326 \r
327   public void sendSelection()\r
328   {\r
329     getStructureSelectionManager().sendSelection(\r
330                     new SequenceGroup(getSelectionGroup()),\r
331                     new ColumnSelection(getColumnSelection()), this);\r
332   }\r
333 \r
334   /**\r
335    * Returns an instance of the StructureSelectionManager scoped to this applet\r
336    * instance.\r
337    * \r
338    * @return\r
339    */\r
340   @Override\r
341   public StructureSelectionManager getStructureSelectionManager()\r
342   {\r
343     return StructureSelectionManager.getStructureSelectionManager(applet);\r
344   }\r
345 \r
346   /**\r
347    * synthesize a column selection if none exists so it covers the given\r
348    * selection group. if wholewidth is false, no column selection is made if the\r
349    * selection group covers the whole alignment width.\r
350    * \r
351    * @param sg\r
352    * @param wholewidth\r
353    */\r
354   public void expandColSelection(SequenceGroup sg, boolean wholewidth)\r
355   {\r
356     int sgs, sge;\r
357     if (sg != null\r
358             && (sgs = sg.getStartRes()) >= 0\r
359             && sg.getStartRes() <= (sge = sg.getEndRes())\r
360             && (colSel == null || colSel.getSelected() == null || colSel\r
361                     .getSelected().size() == 0))\r
362     {\r
363       if (!wholewidth && alignment.getWidth() == (1 + sge - sgs))\r
364       {\r
365         // do nothing\r
366         return;\r
367       }\r
368       if (colSel == null)\r
369       {\r
370         colSel = new ColumnSelection();\r
371       }\r
372       for (int cspos = sg.getStartRes(); cspos <= sg.getEndRes(); cspos++)\r
373       {\r
374         colSel.addElement(cspos);\r
375       }\r
376     }\r
377   }\r
378 \r
379   public boolean isNormaliseSequenceLogo()\r
380   {\r
381     return normaliseSequenceLogo;\r
382   }\r
383 \r
384   public void setNormaliseSequenceLogo(boolean state)\r
385   {\r
386     normaliseSequenceLogo = state;\r
387   }\r
388 \r
389   /**\r
390    * \r
391    * @return true if alignment characters should be displayed\r
392    */\r
393   public boolean isValidCharWidth()\r
394   {\r
395     return validCharWidth;\r
396   }\r
397 \r
398   public AnnotationColumnChooser getAnnotationColumnSelectionState()\r
399   {\r
400     return annotationColumnSelectionState;\r
401   }\r
402 \r
403   public void setAnnotationColumnSelectionState(\r
404           AnnotationColumnChooser annotationColumnSelectionState)\r
405   {\r
406     this.annotationColumnSelectionState = annotationColumnSelectionState;\r
407   }\r
408 \r
409   @Override\r
410   public void mirrorCommand(CommandI command, boolean undo,\r
411           StructureSelectionManager ssm, VamsasSource source)\r
412   {\r
413     // TODO refactor so this can be pulled up to superclass or controller\r
414     /*\r
415      * Do nothing unless we are a 'complement' of the source. May replace this\r
416      * with direct calls not via SSM.\r
417      */\r
418     if (source instanceof AlignViewportI\r
419             && ((AlignViewportI) source).getCodingComplement() == this)\r
420     {\r
421       // ok to continue;\r
422     }\r
423     else\r
424     {\r
425       return;\r
426     }\r
427 \r
428     CommandI mappedCommand = ssm.mapCommand(command, undo, getAlignment(),\r
429             getGapCharacter());\r
430     if (mappedCommand != null)\r
431     {\r
432       mappedCommand.doCommand(null);\r
433       firePropertyChange("alignment", null, getAlignment().getSequences());\r
434 \r
435       // ap.scalePanelHolder.repaint();\r
436       // ap.repaint();\r
437     }\r
438   }\r
439 \r
440   @Override\r
441   public VamsasSource getVamsasSource()\r
442   {\r
443     return this;\r
444   }\r
445 \r
446   /**\r
447    * If this viewport has a (Protein/cDNA) complement, then scroll the\r
448    * complementary alignment to match this one.\r
449    */\r
450   public void scrollComplementaryAlignment(AlignmentPanel complementPanel)\r
451   {\r
452     if (complementPanel == null)\r
453     {\r
454       return;\r
455     }\r
456 \r
457     /*\r
458      * Populate a SearchResults object with the mapped location to scroll to. If\r
459      * there is no complement, or it is not following highlights, or no mapping\r
460      * is found, the result will be empty.\r
461      */\r
462     SearchResults sr = new SearchResults();\r
463     int seqOffset = findComplementScrollTarget(sr);\r
464     if (!sr.isEmpty())\r
465     {\r
466       complementPanel.setFollowingComplementScroll(true);\r
467       complementPanel.scrollToCentre(sr, seqOffset);\r
468     }\r
469   }\r
470 \r
471 \r
472 }\r