JAL-1690 'scale protein as cDNA' options in Preferences, FontChooser
[jalview.git] / src / jalview / appletgui / SplitFrame.java
1 package jalview.appletgui;
2
3 import java.awt.BorderLayout;
4 import java.awt.Dimension;
5 import java.awt.GridLayout;
6 import java.awt.Panel;
7
8 import jalview.analysis.AlignmentUtils;
9 import jalview.api.AlignmentViewPanel;
10 import jalview.api.ViewStyleI;
11 import jalview.bin.JalviewLite;
12 import jalview.datamodel.AlignmentI;
13 import jalview.structure.StructureSelectionManager;
14
15 public class SplitFrame extends EmbmenuFrame
16 {
17   private static final long serialVersionUID = 1L;
18
19   private AlignFrame topFrame;
20
21   private AlignFrame bottomFrame;
22
23   private Panel outermost;
24
25   /**
26    * Constructor
27    */
28   public SplitFrame(AlignFrame af1, AlignFrame af2)
29   {
30     topFrame = af1;
31     bottomFrame = af2;
32     init();
33   }
34
35   /**
36    * Creates a Panel containing two Panels, and adds the first and second
37    * AlignFrame's components to each. At this stage we have not yet committed to
38    * whether the enclosing panel will be added to this frame, for display as a
39    * separate frame, or added to the applet (embedded mode).
40    */
41   public void init()
42   {
43     constructSplit();
44
45     /*
46      * Try to make and add dna/protein sequence mappings
47      */
48     final AlignViewport topViewport = topFrame.viewport;
49     final AlignViewport bottomViewport = bottomFrame.viewport;
50     final AlignmentI topAlignment = topViewport.getAlignment();
51     final AlignmentI bottomAlignment = bottomViewport.getAlignment();
52     AlignViewport cdna = topAlignment.isNucleotide() ? topViewport
53             : (bottomAlignment.isNucleotide() ? bottomViewport : null);
54     AlignViewport protein = !topAlignment.isNucleotide() ? topViewport
55             : (!bottomAlignment.isNucleotide() ? bottomViewport : null);
56
57     boolean mapped = AlignmentUtils.mapProteinToCdna(
58             protein.getAlignment(), cdna.getAlignment());
59     if (mapped)
60     {
61       final StructureSelectionManager ssm = StructureSelectionManager
62               .getStructureSelectionManager(topViewport.applet);
63       ssm.addMappings(protein.getAlignment().getCodonFrames());
64       topViewport.setCodingComplement(bottomViewport);
65       ssm.addCommandListener(cdna);
66       ssm.addCommandListener(protein);
67     }
68
69     /*
70      * Now mappings exist, can compute cDNA consensus on protein alignment
71      */
72     protein.initComplementConsensus();
73     AlignmentViewPanel ap = topAlignment.isNucleotide() ? bottomFrame.alignPanel
74             : topFrame.alignPanel;
75     protein.updateConsensus(ap);
76
77     adjustLayout();
78   }
79
80   /**
81    * 
82    */
83   protected void constructSplit()
84   {
85     setMenuBar(null);
86     outermost = new Panel(new GridLayout(2, 1));
87
88     Panel topPanel = new Panel();
89     Panel bottomPanel = new Panel();
90     outermost.add(topPanel);
91     outermost.add(bottomPanel);
92
93     addAlignFrameComponents(topFrame, topPanel);
94     addAlignFrameComponents(bottomFrame, bottomPanel);
95   }
96
97   /**
98    * Make any adjustments to the layout
99    */
100   protected void adjustLayout()
101   {
102     AlignViewport cdna = topFrame.getAlignViewport().getAlignment()
103             .isNucleotide() ? topFrame.viewport : bottomFrame.viewport;
104     AlignViewport protein = cdna == topFrame.viewport ? bottomFrame.viewport
105             : topFrame.viewport;
106
107     /*
108      * Ensure sequence ids are the same width for good alignment.
109      */
110     // TODO should do this via av.getViewStyle/setViewStyle
111     // however at present av.viewStyle is not set in IdPanel.fontChanged
112     int w1 = topFrame.alignPanel.idPanel.idCanvas.getWidth();
113     int w2 = bottomFrame.alignPanel.idPanel.idCanvas.getWidth();
114     int w3 = Math.max(w1, w2);
115     if (w1 != w3)
116     {
117       Dimension d = topFrame.alignPanel.idPanel.idCanvas.getSize();
118       topFrame.alignPanel.idPanel.idCanvas.setSize(new Dimension(w3,
119               d.height));
120     }
121     if (w2 != w3)
122     {
123       Dimension d = bottomFrame.alignPanel.idPanel.idCanvas.getSize();
124       bottomFrame.alignPanel.idPanel.idCanvas.setSize(new Dimension(w3,
125               d.height));
126     }
127
128     /*
129      * Scale protein to either 1 or 3 times character width of dna
130      */
131     if (protein != null && cdna != null)
132     {
133       ViewStyleI vs = protein.getViewStyle();
134       int scale = vs.isScaleProteinAsCdna() ? 3 : 1;
135       vs.setCharWidth(scale * cdna.getViewStyle().getCharWidth());
136       protein.setViewStyle(vs);
137     }
138   }
139
140   /**
141    * Add the menu bar, alignment panel and status bar from the AlignFrame to the
142    * panel. The menu bar is a panel 'reconstructed' from the AlignFrame's frame
143    * menu bar. This allows each half of the SplitFrame to have its own menu bar.
144    * 
145    * @param af
146    * @param panel
147    */
148   private void addAlignFrameComponents(AlignFrame af, Panel panel)
149   {
150     panel.setLayout(new BorderLayout());
151     Panel menuPanel = af
152             .makeEmbeddedPopupMenu(af.getMenuBar(), true, false);
153     panel.add(menuPanel, BorderLayout.NORTH);
154     panel.add(af.statusBar, BorderLayout.SOUTH);
155     panel.add(af.alignPanel, BorderLayout.CENTER);
156
157     af.setSplitFrame(this);
158   }
159
160   /**
161    * Display the content panel either as a new frame or embedded in the applet.
162    * 
163    * @param embedded
164    * @param applet
165    */
166   public void addToDisplay(boolean embedded, JalviewLite applet)
167   {
168     createSplitFrameWindow(embedded, applet);
169     validate();
170     topFrame.alignPanel.adjustAnnotationHeight();
171     topFrame.alignPanel.paintAlignment(true);
172     bottomFrame.alignPanel.adjustAnnotationHeight();
173     bottomFrame.alignPanel.paintAlignment(true);
174   }
175
176   /**
177    * Either show the content panel in this frame as a new frame, or (if
178    * embed=true) add it to the applet container instead.
179    * 
180    * @param embed
181    * @param applet
182    */
183   protected void createSplitFrameWindow(boolean embed, JalviewLite applet)
184   {
185     if (embed)
186     {
187       applet.add(outermost);
188       applet.validate();
189     }
190     else
191     {
192       this.add(outermost);
193       int width = Math.max(topFrame.frameWidth,
194               bottomFrame.frameWidth);
195       int height = topFrame.frameHeight + bottomFrame.frameHeight;
196       jalview.bin.JalviewLite
197               .addFrame(this, this.getTitle(), width, height);
198     }
199   }
200 }